162306a36Sopenharmony_ci#!/usr/bin/env python3 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci# Controls the openvswitch module. Part of the kselftest suite, but 562306a36Sopenharmony_ci# can be used for some diagnostic purpose as well. 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciimport argparse 862306a36Sopenharmony_ciimport errno 962306a36Sopenharmony_ciimport ipaddress 1062306a36Sopenharmony_ciimport logging 1162306a36Sopenharmony_ciimport multiprocessing 1262306a36Sopenharmony_ciimport re 1362306a36Sopenharmony_ciimport struct 1462306a36Sopenharmony_ciimport sys 1562306a36Sopenharmony_ciimport time 1662306a36Sopenharmony_ciimport types 1762306a36Sopenharmony_ciimport uuid 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_citry: 2062306a36Sopenharmony_ci from pyroute2 import NDB 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci from pyroute2.netlink import NLA_F_NESTED 2362306a36Sopenharmony_ci from pyroute2.netlink import NLM_F_ACK 2462306a36Sopenharmony_ci from pyroute2.netlink import NLM_F_DUMP 2562306a36Sopenharmony_ci from pyroute2.netlink import NLM_F_REQUEST 2662306a36Sopenharmony_ci from pyroute2.netlink import genlmsg 2762306a36Sopenharmony_ci from pyroute2.netlink import nla 2862306a36Sopenharmony_ci from pyroute2.netlink import nlmsg_atoms 2962306a36Sopenharmony_ci from pyroute2.netlink.exceptions import NetlinkError 3062306a36Sopenharmony_ci from pyroute2.netlink.generic import GenericNetlinkSocket 3162306a36Sopenharmony_ci import pyroute2 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciexcept ModuleNotFoundError: 3462306a36Sopenharmony_ci print("Need to install the python pyroute2 package >= 0.6.") 3562306a36Sopenharmony_ci sys.exit(0) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ciOVS_DATAPATH_FAMILY = "ovs_datapath" 3962306a36Sopenharmony_ciOVS_VPORT_FAMILY = "ovs_vport" 4062306a36Sopenharmony_ciOVS_FLOW_FAMILY = "ovs_flow" 4162306a36Sopenharmony_ciOVS_PACKET_FAMILY = "ovs_packet" 4262306a36Sopenharmony_ciOVS_METER_FAMILY = "ovs_meter" 4362306a36Sopenharmony_ciOVS_CT_LIMIT_FAMILY = "ovs_ct_limit" 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciOVS_DATAPATH_VERSION = 2 4662306a36Sopenharmony_ciOVS_DP_CMD_NEW = 1 4762306a36Sopenharmony_ciOVS_DP_CMD_DEL = 2 4862306a36Sopenharmony_ciOVS_DP_CMD_GET = 3 4962306a36Sopenharmony_ciOVS_DP_CMD_SET = 4 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciOVS_VPORT_CMD_NEW = 1 5262306a36Sopenharmony_ciOVS_VPORT_CMD_DEL = 2 5362306a36Sopenharmony_ciOVS_VPORT_CMD_GET = 3 5462306a36Sopenharmony_ciOVS_VPORT_CMD_SET = 4 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciOVS_FLOW_CMD_NEW = 1 5762306a36Sopenharmony_ciOVS_FLOW_CMD_DEL = 2 5862306a36Sopenharmony_ciOVS_FLOW_CMD_GET = 3 5962306a36Sopenharmony_ciOVS_FLOW_CMD_SET = 4 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cidef macstr(mac): 6362306a36Sopenharmony_ci outstr = ":".join(["%02X" % i for i in mac]) 6462306a36Sopenharmony_ci return outstr 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cidef strcspn(str1, str2): 6862306a36Sopenharmony_ci tot = 0 6962306a36Sopenharmony_ci for char in str1: 7062306a36Sopenharmony_ci if str2.find(char) != -1: 7162306a36Sopenharmony_ci return tot 7262306a36Sopenharmony_ci tot += 1 7362306a36Sopenharmony_ci return tot 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cidef strspn(str1, str2): 7762306a36Sopenharmony_ci tot = 0 7862306a36Sopenharmony_ci for char in str1: 7962306a36Sopenharmony_ci if str2.find(char) == -1: 8062306a36Sopenharmony_ci return tot 8162306a36Sopenharmony_ci tot += 1 8262306a36Sopenharmony_ci return tot 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cidef intparse(statestr, defmask="0xffffffff"): 8662306a36Sopenharmony_ci totalparse = strspn(statestr, "0123456789abcdefABCDEFx/") 8762306a36Sopenharmony_ci # scan until "/" 8862306a36Sopenharmony_ci count = strspn(statestr, "x0123456789abcdefABCDEF") 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci firstnum = statestr[:count] 9162306a36Sopenharmony_ci if firstnum[-1] == "/": 9262306a36Sopenharmony_ci firstnum = firstnum[:-1] 9362306a36Sopenharmony_ci k = int(firstnum, 0) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci m = None 9662306a36Sopenharmony_ci if defmask is not None: 9762306a36Sopenharmony_ci secondnum = defmask 9862306a36Sopenharmony_ci if statestr[count] == "/": 9962306a36Sopenharmony_ci secondnum = statestr[count + 1 :] # this is wrong... 10062306a36Sopenharmony_ci m = int(secondnum, 0) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci return statestr[totalparse + 1 :], k, m 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cidef parse_flags(flag_str, flag_vals): 10662306a36Sopenharmony_ci bitResult = 0 10762306a36Sopenharmony_ci maskResult = 0 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci if len(flag_str) == 0: 11062306a36Sopenharmony_ci return flag_str, bitResult, maskResult 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if flag_str[0].isdigit(): 11362306a36Sopenharmony_ci idx = 0 11462306a36Sopenharmony_ci while flag_str[idx].isdigit() or flag_str[idx] == "x": 11562306a36Sopenharmony_ci idx += 1 11662306a36Sopenharmony_ci digits = flag_str[:idx] 11762306a36Sopenharmony_ci flag_str = flag_str[idx:] 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci bitResult = int(digits, 0) 12062306a36Sopenharmony_ci maskResult = int(digits, 0) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci while len(flag_str) > 0 and (flag_str[0] == "+" or flag_str[0] == "-"): 12362306a36Sopenharmony_ci if flag_str[0] == "+": 12462306a36Sopenharmony_ci setFlag = True 12562306a36Sopenharmony_ci elif flag_str[0] == "-": 12662306a36Sopenharmony_ci setFlag = False 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci flag_str = flag_str[1:] 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci flag_len = 0 13162306a36Sopenharmony_ci while ( 13262306a36Sopenharmony_ci flag_str[flag_len] != "+" 13362306a36Sopenharmony_ci and flag_str[flag_len] != "-" 13462306a36Sopenharmony_ci and flag_str[flag_len] != "," 13562306a36Sopenharmony_ci and flag_str[flag_len] != ")" 13662306a36Sopenharmony_ci ): 13762306a36Sopenharmony_ci flag_len += 1 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci flag = flag_str[0:flag_len] 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if flag in flag_vals: 14262306a36Sopenharmony_ci if maskResult & flag_vals[flag]: 14362306a36Sopenharmony_ci raise KeyError( 14462306a36Sopenharmony_ci "Flag %s set once, cannot be set in multiples" % flag 14562306a36Sopenharmony_ci ) 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if setFlag: 14862306a36Sopenharmony_ci bitResult |= flag_vals[flag] 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci maskResult |= flag_vals[flag] 15162306a36Sopenharmony_ci else: 15262306a36Sopenharmony_ci raise KeyError("Missing flag value: %s" % flag) 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci flag_str = flag_str[flag_len:] 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return flag_str, bitResult, maskResult 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cidef parse_ct_state(statestr): 16062306a36Sopenharmony_ci ct_flags = { 16162306a36Sopenharmony_ci "new": 1 << 0, 16262306a36Sopenharmony_ci "est": 1 << 1, 16362306a36Sopenharmony_ci "rel": 1 << 2, 16462306a36Sopenharmony_ci "rpl": 1 << 3, 16562306a36Sopenharmony_ci "inv": 1 << 4, 16662306a36Sopenharmony_ci "trk": 1 << 5, 16762306a36Sopenharmony_ci "snat": 1 << 6, 16862306a36Sopenharmony_ci "dnat": 1 << 7, 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return parse_flags(statestr, ct_flags) 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cidef convert_mac(data): 17562306a36Sopenharmony_ci def to_bytes(mac): 17662306a36Sopenharmony_ci mac_split = mac.split(":") 17762306a36Sopenharmony_ci ret = bytearray([int(i, 16) for i in mac_split]) 17862306a36Sopenharmony_ci return bytes(ret) 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci mac_str, _, mask_str = data.partition('/') 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if not mac_str: 18362306a36Sopenharmony_ci mac_str = mask_str = "00:00:00:00:00:00" 18462306a36Sopenharmony_ci elif not mask_str: 18562306a36Sopenharmony_ci mask_str = "FF:FF:FF:FF:FF:FF" 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return to_bytes(mac_str), to_bytes(mask_str) 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cidef convert_ipv4(data): 19062306a36Sopenharmony_ci ip, _, mask = data.partition('/') 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci if not ip: 19362306a36Sopenharmony_ci ip = mask = 0 19462306a36Sopenharmony_ci elif not mask: 19562306a36Sopenharmony_ci mask = 0xFFFFFFFF 19662306a36Sopenharmony_ci elif mask.isdigit(): 19762306a36Sopenharmony_ci mask = (0xFFFFFFFF << (32 - int(mask))) & 0xFFFFFFFF 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return int(ipaddress.IPv4Address(ip)), int(ipaddress.IPv4Address(mask)) 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cidef convert_int(size): 20262306a36Sopenharmony_ci def convert_int_sized(data): 20362306a36Sopenharmony_ci value, _, mask = data.partition('/') 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if not value: 20662306a36Sopenharmony_ci return 0, 0 20762306a36Sopenharmony_ci elif not mask: 20862306a36Sopenharmony_ci return int(value, 0), pow(2, size) - 1 20962306a36Sopenharmony_ci else: 21062306a36Sopenharmony_ci return int(value, 0), int(mask, 0) 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return convert_int_sized 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cidef parse_starts_block(block_str, scanstr, returnskipped, scanregex=False): 21562306a36Sopenharmony_ci if scanregex: 21662306a36Sopenharmony_ci m = re.search(scanstr, block_str) 21762306a36Sopenharmony_ci if m is None: 21862306a36Sopenharmony_ci if returnskipped: 21962306a36Sopenharmony_ci return block_str 22062306a36Sopenharmony_ci return False 22162306a36Sopenharmony_ci if returnskipped: 22262306a36Sopenharmony_ci block_str = block_str[len(m.group(0)) :] 22362306a36Sopenharmony_ci return block_str 22462306a36Sopenharmony_ci return True 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if block_str.startswith(scanstr): 22762306a36Sopenharmony_ci if returnskipped: 22862306a36Sopenharmony_ci block_str = block_str[len(scanstr) :] 22962306a36Sopenharmony_ci else: 23062306a36Sopenharmony_ci return True 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if returnskipped: 23362306a36Sopenharmony_ci return block_str 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return False 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_cidef parse_extract_field( 23962306a36Sopenharmony_ci block_str, fieldstr, scanfmt, convert, masked=False, defval=None 24062306a36Sopenharmony_ci): 24162306a36Sopenharmony_ci if fieldstr and not block_str.startswith(fieldstr): 24262306a36Sopenharmony_ci return block_str, defval 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if fieldstr: 24562306a36Sopenharmony_ci str_skiplen = len(fieldstr) 24662306a36Sopenharmony_ci str_skipped = block_str[str_skiplen:] 24762306a36Sopenharmony_ci if str_skiplen == 0: 24862306a36Sopenharmony_ci return str_skipped, defval 24962306a36Sopenharmony_ci else: 25062306a36Sopenharmony_ci str_skiplen = 0 25162306a36Sopenharmony_ci str_skipped = block_str 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci m = re.search(scanfmt, str_skipped) 25462306a36Sopenharmony_ci if m is None: 25562306a36Sopenharmony_ci raise ValueError("Bad fmt string") 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci data = m.group(0) 25862306a36Sopenharmony_ci if convert: 25962306a36Sopenharmony_ci data = convert(m.group(0)) 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci str_skipped = str_skipped[len(m.group(0)) :] 26262306a36Sopenharmony_ci if masked: 26362306a36Sopenharmony_ci if str_skipped[0] == "/": 26462306a36Sopenharmony_ci raise ValueError("Masking support TBD...") 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci str_skipped = str_skipped[strspn(str_skipped, ", ") :] 26762306a36Sopenharmony_ci return str_skipped, data 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciclass ovs_dp_msg(genlmsg): 27162306a36Sopenharmony_ci # include the OVS version 27262306a36Sopenharmony_ci # We need a custom header rather than just being able to rely on 27362306a36Sopenharmony_ci # genlmsg because fields ends up not expressing everything correctly 27462306a36Sopenharmony_ci # if we use the canonical example of setting fields = (('customfield',),) 27562306a36Sopenharmony_ci fields = genlmsg.fields + (("dpifindex", "I"),) 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ciclass ovsactions(nla): 27962306a36Sopenharmony_ci nla_flags = NLA_F_NESTED 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci nla_map = ( 28262306a36Sopenharmony_ci ("OVS_ACTION_ATTR_UNSPEC", "none"), 28362306a36Sopenharmony_ci ("OVS_ACTION_ATTR_OUTPUT", "uint32"), 28462306a36Sopenharmony_ci ("OVS_ACTION_ATTR_USERSPACE", "userspace"), 28562306a36Sopenharmony_ci ("OVS_ACTION_ATTR_SET", "none"), 28662306a36Sopenharmony_ci ("OVS_ACTION_ATTR_PUSH_VLAN", "none"), 28762306a36Sopenharmony_ci ("OVS_ACTION_ATTR_POP_VLAN", "flag"), 28862306a36Sopenharmony_ci ("OVS_ACTION_ATTR_SAMPLE", "none"), 28962306a36Sopenharmony_ci ("OVS_ACTION_ATTR_RECIRC", "uint32"), 29062306a36Sopenharmony_ci ("OVS_ACTION_ATTR_HASH", "none"), 29162306a36Sopenharmony_ci ("OVS_ACTION_ATTR_PUSH_MPLS", "none"), 29262306a36Sopenharmony_ci ("OVS_ACTION_ATTR_POP_MPLS", "flag"), 29362306a36Sopenharmony_ci ("OVS_ACTION_ATTR_SET_MASKED", "none"), 29462306a36Sopenharmony_ci ("OVS_ACTION_ATTR_CT", "ctact"), 29562306a36Sopenharmony_ci ("OVS_ACTION_ATTR_TRUNC", "uint32"), 29662306a36Sopenharmony_ci ("OVS_ACTION_ATTR_PUSH_ETH", "none"), 29762306a36Sopenharmony_ci ("OVS_ACTION_ATTR_POP_ETH", "flag"), 29862306a36Sopenharmony_ci ("OVS_ACTION_ATTR_CT_CLEAR", "flag"), 29962306a36Sopenharmony_ci ("OVS_ACTION_ATTR_PUSH_NSH", "none"), 30062306a36Sopenharmony_ci ("OVS_ACTION_ATTR_POP_NSH", "flag"), 30162306a36Sopenharmony_ci ("OVS_ACTION_ATTR_METER", "none"), 30262306a36Sopenharmony_ci ("OVS_ACTION_ATTR_CLONE", "recursive"), 30362306a36Sopenharmony_ci ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"), 30462306a36Sopenharmony_ci ("OVS_ACTION_ATTR_ADD_MPLS", "none"), 30562306a36Sopenharmony_ci ("OVS_ACTION_ATTR_DEC_TTL", "none"), 30662306a36Sopenharmony_ci ("OVS_ACTION_ATTR_DROP", "uint32"), 30762306a36Sopenharmony_ci ) 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci class ctact(nla): 31062306a36Sopenharmony_ci nla_flags = NLA_F_NESTED 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci nla_map = ( 31362306a36Sopenharmony_ci ("OVS_CT_ATTR_NONE", "none"), 31462306a36Sopenharmony_ci ("OVS_CT_ATTR_COMMIT", "flag"), 31562306a36Sopenharmony_ci ("OVS_CT_ATTR_ZONE", "uint16"), 31662306a36Sopenharmony_ci ("OVS_CT_ATTR_MARK", "none"), 31762306a36Sopenharmony_ci ("OVS_CT_ATTR_LABELS", "none"), 31862306a36Sopenharmony_ci ("OVS_CT_ATTR_HELPER", "asciiz"), 31962306a36Sopenharmony_ci ("OVS_CT_ATTR_NAT", "natattr"), 32062306a36Sopenharmony_ci ("OVS_CT_ATTR_FORCE_COMMIT", "flag"), 32162306a36Sopenharmony_ci ("OVS_CT_ATTR_EVENTMASK", "uint32"), 32262306a36Sopenharmony_ci ("OVS_CT_ATTR_TIMEOUT", "asciiz"), 32362306a36Sopenharmony_ci ) 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci class natattr(nla): 32662306a36Sopenharmony_ci nla_flags = NLA_F_NESTED 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci nla_map = ( 32962306a36Sopenharmony_ci ("OVS_NAT_ATTR_NONE", "none"), 33062306a36Sopenharmony_ci ("OVS_NAT_ATTR_SRC", "flag"), 33162306a36Sopenharmony_ci ("OVS_NAT_ATTR_DST", "flag"), 33262306a36Sopenharmony_ci ("OVS_NAT_ATTR_IP_MIN", "ipaddr"), 33362306a36Sopenharmony_ci ("OVS_NAT_ATTR_IP_MAX", "ipaddr"), 33462306a36Sopenharmony_ci ("OVS_NAT_ATTR_PROTO_MIN", "uint16"), 33562306a36Sopenharmony_ci ("OVS_NAT_ATTR_PROTO_MAX", "uint16"), 33662306a36Sopenharmony_ci ("OVS_NAT_ATTR_PERSISTENT", "flag"), 33762306a36Sopenharmony_ci ("OVS_NAT_ATTR_PROTO_HASH", "flag"), 33862306a36Sopenharmony_ci ("OVS_NAT_ATTR_PROTO_RANDOM", "flag"), 33962306a36Sopenharmony_ci ) 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci def dpstr(self, more=False): 34262306a36Sopenharmony_ci print_str = "nat(" 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_SRC"): 34562306a36Sopenharmony_ci print_str += "src" 34662306a36Sopenharmony_ci elif self.get_attr("OVS_NAT_ATTR_DST"): 34762306a36Sopenharmony_ci print_str += "dst" 34862306a36Sopenharmony_ci else: 34962306a36Sopenharmony_ci print_str += "XXX-unknown-nat" 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_IP_MIN") or self.get_attr( 35262306a36Sopenharmony_ci "OVS_NAT_ATTR_IP_MAX" 35362306a36Sopenharmony_ci ): 35462306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_IP_MIN"): 35562306a36Sopenharmony_ci print_str += "=%s," % str( 35662306a36Sopenharmony_ci self.get_attr("OVS_NAT_ATTR_IP_MIN") 35762306a36Sopenharmony_ci ) 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_IP_MAX"): 36062306a36Sopenharmony_ci print_str += "-%s," % str( 36162306a36Sopenharmony_ci self.get_attr("OVS_NAT_ATTR_IP_MAX") 36262306a36Sopenharmony_ci ) 36362306a36Sopenharmony_ci else: 36462306a36Sopenharmony_ci print_str += "," 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_PROTO_MIN"): 36762306a36Sopenharmony_ci print_str += "proto_min=%d," % self.get_attr( 36862306a36Sopenharmony_ci "OVS_NAT_ATTR_PROTO_MIN" 36962306a36Sopenharmony_ci ) 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_PROTO_MAX"): 37262306a36Sopenharmony_ci print_str += "proto_max=%d," % self.get_attr( 37362306a36Sopenharmony_ci "OVS_NAT_ATTR_PROTO_MAX" 37462306a36Sopenharmony_ci ) 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_PERSISTENT"): 37762306a36Sopenharmony_ci print_str += "persistent," 37862306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_HASH"): 37962306a36Sopenharmony_ci print_str += "hash," 38062306a36Sopenharmony_ci if self.get_attr("OVS_NAT_ATTR_RANDOM"): 38162306a36Sopenharmony_ci print_str += "random" 38262306a36Sopenharmony_ci print_str += ")" 38362306a36Sopenharmony_ci return print_str 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci def dpstr(self, more=False): 38662306a36Sopenharmony_ci print_str = "ct(" 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_COMMIT") is not None: 38962306a36Sopenharmony_ci print_str += "commit," 39062306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_ZONE") is not None: 39162306a36Sopenharmony_ci print_str += "zone=%d," % self.get_attr("OVS_CT_ATTR_ZONE") 39262306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_HELPER") is not None: 39362306a36Sopenharmony_ci print_str += "helper=%s," % self.get_attr("OVS_CT_ATTR_HELPER") 39462306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_NAT") is not None: 39562306a36Sopenharmony_ci print_str += self.get_attr("OVS_CT_ATTR_NAT").dpstr(more) 39662306a36Sopenharmony_ci print_str += "," 39762306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_FORCE_COMMIT") is not None: 39862306a36Sopenharmony_ci print_str += "force," 39962306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_EVENTMASK") is not None: 40062306a36Sopenharmony_ci print_str += "emask=0x%X," % self.get_attr( 40162306a36Sopenharmony_ci "OVS_CT_ATTR_EVENTMASK" 40262306a36Sopenharmony_ci ) 40362306a36Sopenharmony_ci if self.get_attr("OVS_CT_ATTR_TIMEOUT") is not None: 40462306a36Sopenharmony_ci print_str += "timeout=%s" % self.get_attr( 40562306a36Sopenharmony_ci "OVS_CT_ATTR_TIMEOUT" 40662306a36Sopenharmony_ci ) 40762306a36Sopenharmony_ci print_str += ")" 40862306a36Sopenharmony_ci return print_str 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci class userspace(nla): 41162306a36Sopenharmony_ci nla_flags = NLA_F_NESTED 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci nla_map = ( 41462306a36Sopenharmony_ci ("OVS_USERSPACE_ATTR_UNUSED", "none"), 41562306a36Sopenharmony_ci ("OVS_USERSPACE_ATTR_PID", "uint32"), 41662306a36Sopenharmony_ci ("OVS_USERSPACE_ATTR_USERDATA", "array(uint8)"), 41762306a36Sopenharmony_ci ("OVS_USERSPACE_ATTR_EGRESS_TUN_PORT", "uint32"), 41862306a36Sopenharmony_ci ) 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci def dpstr(self, more=False): 42162306a36Sopenharmony_ci print_str = "userspace(" 42262306a36Sopenharmony_ci if self.get_attr("OVS_USERSPACE_ATTR_PID") is not None: 42362306a36Sopenharmony_ci print_str += "pid=%d," % self.get_attr( 42462306a36Sopenharmony_ci "OVS_USERSPACE_ATTR_PID" 42562306a36Sopenharmony_ci ) 42662306a36Sopenharmony_ci if self.get_attr("OVS_USERSPACE_ATTR_USERDATA") is not None: 42762306a36Sopenharmony_ci print_str += "userdata=" 42862306a36Sopenharmony_ci for f in self.get_attr("OVS_USERSPACE_ATTR_USERDATA"): 42962306a36Sopenharmony_ci print_str += "%x." % f 43062306a36Sopenharmony_ci if self.get_attr("OVS_USERSPACE_ATTR_TUN_PORT") is not None: 43162306a36Sopenharmony_ci print_str += "egress_tun_port=%d" % self.get_attr( 43262306a36Sopenharmony_ci "OVS_USERSPACE_ATTR_TUN_PORT" 43362306a36Sopenharmony_ci ) 43462306a36Sopenharmony_ci print_str += ")" 43562306a36Sopenharmony_ci return print_str 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci def dpstr(self, more=False): 43862306a36Sopenharmony_ci print_str = "" 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci for field in self.nla_map: 44162306a36Sopenharmony_ci if field[1] == "none" or self.get_attr(field[0]) is None: 44262306a36Sopenharmony_ci continue 44362306a36Sopenharmony_ci if print_str != "": 44462306a36Sopenharmony_ci print_str += "," 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci if field[1] == "uint32": 44762306a36Sopenharmony_ci if field[0] == "OVS_ACTION_ATTR_OUTPUT": 44862306a36Sopenharmony_ci print_str += "%d" % int(self.get_attr(field[0])) 44962306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_RECIRC": 45062306a36Sopenharmony_ci print_str += "recirc(0x%x)" % int(self.get_attr(field[0])) 45162306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_TRUNC": 45262306a36Sopenharmony_ci print_str += "trunc(%d)" % int(self.get_attr(field[0])) 45362306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_DROP": 45462306a36Sopenharmony_ci print_str += "drop(%d)" % int(self.get_attr(field[0])) 45562306a36Sopenharmony_ci elif field[1] == "flag": 45662306a36Sopenharmony_ci if field[0] == "OVS_ACTION_ATTR_CT_CLEAR": 45762306a36Sopenharmony_ci print_str += "ct_clear" 45862306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_POP_VLAN": 45962306a36Sopenharmony_ci print_str += "pop_vlan" 46062306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_POP_ETH": 46162306a36Sopenharmony_ci print_str += "pop_eth" 46262306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_POP_NSH": 46362306a36Sopenharmony_ci print_str += "pop_nsh" 46462306a36Sopenharmony_ci elif field[0] == "OVS_ACTION_ATTR_POP_MPLS": 46562306a36Sopenharmony_ci print_str += "pop_mpls" 46662306a36Sopenharmony_ci else: 46762306a36Sopenharmony_ci datum = self.get_attr(field[0]) 46862306a36Sopenharmony_ci if field[0] == "OVS_ACTION_ATTR_CLONE": 46962306a36Sopenharmony_ci print_str += "clone(" 47062306a36Sopenharmony_ci print_str += datum.dpstr(more) 47162306a36Sopenharmony_ci print_str += ")" 47262306a36Sopenharmony_ci else: 47362306a36Sopenharmony_ci print_str += datum.dpstr(more) 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return print_str 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci def parse(self, actstr): 47862306a36Sopenharmony_ci totallen = len(actstr) 47962306a36Sopenharmony_ci while len(actstr) != 0: 48062306a36Sopenharmony_ci parsed = False 48162306a36Sopenharmony_ci parencount = 0 48262306a36Sopenharmony_ci if actstr.startswith("drop"): 48362306a36Sopenharmony_ci # If no reason is provided, the implicit drop is used (i.e no 48462306a36Sopenharmony_ci # action). If some reason is given, an explicit action is used. 48562306a36Sopenharmony_ci reason = None 48662306a36Sopenharmony_ci if actstr.startswith("drop("): 48762306a36Sopenharmony_ci parencount += 1 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci actstr, reason = parse_extract_field( 49062306a36Sopenharmony_ci actstr, 49162306a36Sopenharmony_ci "drop(", 49262306a36Sopenharmony_ci "([0-9]+)", 49362306a36Sopenharmony_ci lambda x: int(x, 0), 49462306a36Sopenharmony_ci False, 49562306a36Sopenharmony_ci None, 49662306a36Sopenharmony_ci ) 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if reason is not None: 49962306a36Sopenharmony_ci self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason]) 50062306a36Sopenharmony_ci parsed = True 50162306a36Sopenharmony_ci else: 50262306a36Sopenharmony_ci actstr = actstr[len("drop"): ] 50362306a36Sopenharmony_ci return (totallen - len(actstr)) 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci elif parse_starts_block(actstr, "^(\d+)", False, True): 50662306a36Sopenharmony_ci actstr, output = parse_extract_field( 50762306a36Sopenharmony_ci actstr, None, "(\d+)", lambda x: int(x), False, "0" 50862306a36Sopenharmony_ci ) 50962306a36Sopenharmony_ci self["attrs"].append(["OVS_ACTION_ATTR_OUTPUT", output]) 51062306a36Sopenharmony_ci parsed = True 51162306a36Sopenharmony_ci elif parse_starts_block(actstr, "recirc(", False): 51262306a36Sopenharmony_ci actstr, recircid = parse_extract_field( 51362306a36Sopenharmony_ci actstr, 51462306a36Sopenharmony_ci "recirc(", 51562306a36Sopenharmony_ci "([0-9a-fA-Fx]+)", 51662306a36Sopenharmony_ci lambda x: int(x, 0), 51762306a36Sopenharmony_ci False, 51862306a36Sopenharmony_ci 0, 51962306a36Sopenharmony_ci ) 52062306a36Sopenharmony_ci parencount += 1 52162306a36Sopenharmony_ci self["attrs"].append(["OVS_ACTION_ATTR_RECIRC", recircid]) 52262306a36Sopenharmony_ci parsed = True 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci parse_flat_map = ( 52562306a36Sopenharmony_ci ("ct_clear", "OVS_ACTION_ATTR_CT_CLEAR"), 52662306a36Sopenharmony_ci ("pop_vlan", "OVS_ACTION_ATTR_POP_VLAN"), 52762306a36Sopenharmony_ci ("pop_eth", "OVS_ACTION_ATTR_POP_ETH"), 52862306a36Sopenharmony_ci ("pop_nsh", "OVS_ACTION_ATTR_POP_NSH"), 52962306a36Sopenharmony_ci ) 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci for flat_act in parse_flat_map: 53262306a36Sopenharmony_ci if parse_starts_block(actstr, flat_act[0], False): 53362306a36Sopenharmony_ci actstr = actstr[len(flat_act[0]):] 53462306a36Sopenharmony_ci self["attrs"].append([flat_act[1]]) 53562306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 53662306a36Sopenharmony_ci parsed = True 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if parse_starts_block(actstr, "clone(", False): 53962306a36Sopenharmony_ci parencount += 1 54062306a36Sopenharmony_ci subacts = ovsactions() 54162306a36Sopenharmony_ci actstr = actstr[len("clone("):] 54262306a36Sopenharmony_ci parsedLen = subacts.parse(actstr) 54362306a36Sopenharmony_ci lst = [] 54462306a36Sopenharmony_ci self["attrs"].append(("OVS_ACTION_ATTR_CLONE", subacts)) 54562306a36Sopenharmony_ci actstr = actstr[parsedLen:] 54662306a36Sopenharmony_ci parsed = True 54762306a36Sopenharmony_ci elif parse_starts_block(actstr, "ct(", False): 54862306a36Sopenharmony_ci parencount += 1 54962306a36Sopenharmony_ci actstr = actstr[len("ct(") :] 55062306a36Sopenharmony_ci ctact = ovsactions.ctact() 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci for scan in ( 55362306a36Sopenharmony_ci ("commit", "OVS_CT_ATTR_COMMIT", None), 55462306a36Sopenharmony_ci ("force_commit", "OVS_CT_ATTR_FORCE_COMMIT", None), 55562306a36Sopenharmony_ci ("zone", "OVS_CT_ATTR_ZONE", int), 55662306a36Sopenharmony_ci ("mark", "OVS_CT_ATTR_MARK", int), 55762306a36Sopenharmony_ci ("helper", "OVS_CT_ATTR_HELPER", lambda x, y: str(x)), 55862306a36Sopenharmony_ci ("timeout", "OVS_CT_ATTR_TIMEOUT", lambda x, y: str(x)), 55962306a36Sopenharmony_ci ): 56062306a36Sopenharmony_ci if actstr.startswith(scan[0]): 56162306a36Sopenharmony_ci actstr = actstr[len(scan[0]) :] 56262306a36Sopenharmony_ci if scan[2] is not None: 56362306a36Sopenharmony_ci if actstr[0] != "=": 56462306a36Sopenharmony_ci raise ValueError("Invalid ct attr") 56562306a36Sopenharmony_ci actstr = actstr[1:] 56662306a36Sopenharmony_ci pos = strcspn(actstr, ",)") 56762306a36Sopenharmony_ci datum = scan[2](actstr[:pos], 0) 56862306a36Sopenharmony_ci ctact["attrs"].append([scan[1], datum]) 56962306a36Sopenharmony_ci actstr = actstr[pos:] 57062306a36Sopenharmony_ci else: 57162306a36Sopenharmony_ci ctact["attrs"].append([scan[1], None]) 57262306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 57362306a36Sopenharmony_ci # it seems strange to put this here, but nat() is a complex 57462306a36Sopenharmony_ci # sub-action and this lets it sit anywhere in the ct() action 57562306a36Sopenharmony_ci if actstr.startswith("nat"): 57662306a36Sopenharmony_ci actstr = actstr[3:] 57762306a36Sopenharmony_ci natact = ovsactions.ctact.natattr() 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if actstr.startswith("("): 58062306a36Sopenharmony_ci parencount += 1 58162306a36Sopenharmony_ci t = None 58262306a36Sopenharmony_ci actstr = actstr[1:] 58362306a36Sopenharmony_ci if actstr.startswith("src"): 58462306a36Sopenharmony_ci t = "OVS_NAT_ATTR_SRC" 58562306a36Sopenharmony_ci actstr = actstr[3:] 58662306a36Sopenharmony_ci elif actstr.startswith("dst"): 58762306a36Sopenharmony_ci t = "OVS_NAT_ATTR_DST" 58862306a36Sopenharmony_ci actstr = actstr[3:] 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci actstr, ip_block_min = parse_extract_field( 59162306a36Sopenharmony_ci actstr, "=", "([0-9a-fA-F\.]+)", str, False 59262306a36Sopenharmony_ci ) 59362306a36Sopenharmony_ci actstr, ip_block_max = parse_extract_field( 59462306a36Sopenharmony_ci actstr, "-", "([0-9a-fA-F\.]+)", str, False 59562306a36Sopenharmony_ci ) 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci actstr, proto_min = parse_extract_field( 59862306a36Sopenharmony_ci actstr, ":", "(\d+)", int, False 59962306a36Sopenharmony_ci ) 60062306a36Sopenharmony_ci actstr, proto_max = parse_extract_field( 60162306a36Sopenharmony_ci actstr, "-", "(\d+)", int, False 60262306a36Sopenharmony_ci ) 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if t is not None: 60562306a36Sopenharmony_ci natact["attrs"].append([t, None]) 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if ip_block_min is not None: 60862306a36Sopenharmony_ci natact["attrs"].append( 60962306a36Sopenharmony_ci ["OVS_NAT_ATTR_IP_MIN", ip_block_min] 61062306a36Sopenharmony_ci ) 61162306a36Sopenharmony_ci if ip_block_max is not None: 61262306a36Sopenharmony_ci natact["attrs"].append( 61362306a36Sopenharmony_ci ["OVS_NAT_ATTR_IP_MAX", ip_block_max] 61462306a36Sopenharmony_ci ) 61562306a36Sopenharmony_ci if proto_min is not None: 61662306a36Sopenharmony_ci natact["attrs"].append( 61762306a36Sopenharmony_ci ["OVS_NAT_ATTR_PROTO_MIN", proto_min] 61862306a36Sopenharmony_ci ) 61962306a36Sopenharmony_ci if proto_max is not None: 62062306a36Sopenharmony_ci natact["attrs"].append( 62162306a36Sopenharmony_ci ["OVS_NAT_ATTR_PROTO_MAX", proto_max] 62262306a36Sopenharmony_ci ) 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci for natscan in ( 62562306a36Sopenharmony_ci ("persistent", "OVS_NAT_ATTR_PERSISTENT"), 62662306a36Sopenharmony_ci ("hash", "OVS_NAT_ATTR_PROTO_HASH"), 62762306a36Sopenharmony_ci ("random", "OVS_NAT_ATTR_PROTO_RANDOM"), 62862306a36Sopenharmony_ci ): 62962306a36Sopenharmony_ci if actstr.startswith(natscan[0]): 63062306a36Sopenharmony_ci actstr = actstr[len(natscan[0]) :] 63162306a36Sopenharmony_ci natact["attrs"].append([natscan[1], None]) 63262306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci ctact["attrs"].append(["OVS_CT_ATTR_NAT", natact]) 63562306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci self["attrs"].append(["OVS_ACTION_ATTR_CT", ctact]) 63862306a36Sopenharmony_ci parsed = True 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 64162306a36Sopenharmony_ci while parencount > 0: 64262306a36Sopenharmony_ci parencount -= 1 64362306a36Sopenharmony_ci actstr = actstr[strspn(actstr, " "):] 64462306a36Sopenharmony_ci if len(actstr) and actstr[0] != ")": 64562306a36Sopenharmony_ci raise ValueError("Action str: '%s' unbalanced" % actstr) 64662306a36Sopenharmony_ci actstr = actstr[1:] 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if len(actstr) and actstr[0] == ")": 64962306a36Sopenharmony_ci return (totallen - len(actstr)) 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci actstr = actstr[strspn(actstr, ", ") :] 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if not parsed: 65462306a36Sopenharmony_ci raise ValueError("Action str: '%s' not supported" % actstr) 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci return (totallen - len(actstr)) 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ciclass ovskey(nla): 66062306a36Sopenharmony_ci nla_flags = NLA_F_NESTED 66162306a36Sopenharmony_ci nla_map = ( 66262306a36Sopenharmony_ci ("OVS_KEY_ATTR_UNSPEC", "none"), 66362306a36Sopenharmony_ci ("OVS_KEY_ATTR_ENCAP", "none"), 66462306a36Sopenharmony_ci ("OVS_KEY_ATTR_PRIORITY", "uint32"), 66562306a36Sopenharmony_ci ("OVS_KEY_ATTR_IN_PORT", "uint32"), 66662306a36Sopenharmony_ci ("OVS_KEY_ATTR_ETHERNET", "ethaddr"), 66762306a36Sopenharmony_ci ("OVS_KEY_ATTR_VLAN", "uint16"), 66862306a36Sopenharmony_ci ("OVS_KEY_ATTR_ETHERTYPE", "be16"), 66962306a36Sopenharmony_ci ("OVS_KEY_ATTR_IPV4", "ovs_key_ipv4"), 67062306a36Sopenharmony_ci ("OVS_KEY_ATTR_IPV6", "ovs_key_ipv6"), 67162306a36Sopenharmony_ci ("OVS_KEY_ATTR_TCP", "ovs_key_tcp"), 67262306a36Sopenharmony_ci ("OVS_KEY_ATTR_UDP", "ovs_key_udp"), 67362306a36Sopenharmony_ci ("OVS_KEY_ATTR_ICMP", "ovs_key_icmp"), 67462306a36Sopenharmony_ci ("OVS_KEY_ATTR_ICMPV6", "ovs_key_icmpv6"), 67562306a36Sopenharmony_ci ("OVS_KEY_ATTR_ARP", "ovs_key_arp"), 67662306a36Sopenharmony_ci ("OVS_KEY_ATTR_ND", "ovs_key_nd"), 67762306a36Sopenharmony_ci ("OVS_KEY_ATTR_SKB_MARK", "uint32"), 67862306a36Sopenharmony_ci ("OVS_KEY_ATTR_TUNNEL", "none"), 67962306a36Sopenharmony_ci ("OVS_KEY_ATTR_SCTP", "ovs_key_sctp"), 68062306a36Sopenharmony_ci ("OVS_KEY_ATTR_TCP_FLAGS", "be16"), 68162306a36Sopenharmony_ci ("OVS_KEY_ATTR_DP_HASH", "uint32"), 68262306a36Sopenharmony_ci ("OVS_KEY_ATTR_RECIRC_ID", "uint32"), 68362306a36Sopenharmony_ci ("OVS_KEY_ATTR_MPLS", "array(ovs_key_mpls)"), 68462306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_STATE", "uint32"), 68562306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_ZONE", "uint16"), 68662306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_MARK", "uint32"), 68762306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_LABELS", "none"), 68862306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", "ovs_key_ct_tuple_ipv4"), 68962306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", "ovs_key_ct_tuple_ipv6"), 69062306a36Sopenharmony_ci ("OVS_KEY_ATTR_NSH", "none"), 69162306a36Sopenharmony_ci ("OVS_KEY_ATTR_PACKET_TYPE", "none"), 69262306a36Sopenharmony_ci ("OVS_KEY_ATTR_ND_EXTENSIONS", "none"), 69362306a36Sopenharmony_ci ("OVS_KEY_ATTR_TUNNEL_INFO", "none"), 69462306a36Sopenharmony_ci ("OVS_KEY_ATTR_IPV6_EXTENSIONS", "none"), 69562306a36Sopenharmony_ci ) 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci class ovs_key_proto(nla): 69862306a36Sopenharmony_ci fields = ( 69962306a36Sopenharmony_ci ("src", "!H"), 70062306a36Sopenharmony_ci ("dst", "!H"), 70162306a36Sopenharmony_ci ) 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci fields_map = ( 70462306a36Sopenharmony_ci ("src", "src", "%d", lambda x: int(x) if x else 0, 70562306a36Sopenharmony_ci convert_int(16)), 70662306a36Sopenharmony_ci ("dst", "dst", "%d", lambda x: int(x) if x else 0, 70762306a36Sopenharmony_ci convert_int(16)), 70862306a36Sopenharmony_ci ) 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci def __init__( 71162306a36Sopenharmony_ci self, 71262306a36Sopenharmony_ci protostr, 71362306a36Sopenharmony_ci data=None, 71462306a36Sopenharmony_ci offset=None, 71562306a36Sopenharmony_ci parent=None, 71662306a36Sopenharmony_ci length=None, 71762306a36Sopenharmony_ci init=None, 71862306a36Sopenharmony_ci ): 71962306a36Sopenharmony_ci self.proto_str = protostr 72062306a36Sopenharmony_ci nla.__init__( 72162306a36Sopenharmony_ci self, 72262306a36Sopenharmony_ci data=data, 72362306a36Sopenharmony_ci offset=offset, 72462306a36Sopenharmony_ci parent=parent, 72562306a36Sopenharmony_ci length=length, 72662306a36Sopenharmony_ci init=init, 72762306a36Sopenharmony_ci ) 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci def parse(self, flowstr, typeInst): 73062306a36Sopenharmony_ci if not flowstr.startswith(self.proto_str): 73162306a36Sopenharmony_ci return None, None 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci k = typeInst() 73462306a36Sopenharmony_ci m = typeInst() 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci flowstr = flowstr[len(self.proto_str) :] 73762306a36Sopenharmony_ci if flowstr.startswith("("): 73862306a36Sopenharmony_ci flowstr = flowstr[1:] 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci keybits = b"" 74162306a36Sopenharmony_ci maskbits = b"" 74262306a36Sopenharmony_ci for f in self.fields_map: 74362306a36Sopenharmony_ci if flowstr.startswith(f[1]): 74462306a36Sopenharmony_ci # the following assumes that the field looks 74562306a36Sopenharmony_ci # something like 'field.' where '.' is a 74662306a36Sopenharmony_ci # character that we don't exactly care about. 74762306a36Sopenharmony_ci flowstr = flowstr[len(f[1]) + 1 :] 74862306a36Sopenharmony_ci splitchar = 0 74962306a36Sopenharmony_ci for c in flowstr: 75062306a36Sopenharmony_ci if c == "," or c == ")": 75162306a36Sopenharmony_ci break 75262306a36Sopenharmony_ci splitchar += 1 75362306a36Sopenharmony_ci data = flowstr[:splitchar] 75462306a36Sopenharmony_ci flowstr = flowstr[splitchar:] 75562306a36Sopenharmony_ci else: 75662306a36Sopenharmony_ci data = "" 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if len(f) > 4: 75962306a36Sopenharmony_ci k[f[0]], m[f[0]] = f[4](data) 76062306a36Sopenharmony_ci else: 76162306a36Sopenharmony_ci k[f[0]] = f[3](data) 76262306a36Sopenharmony_ci m[f[0]] = f[3](data) 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci flowstr = flowstr[strspn(flowstr, ", ") :] 76562306a36Sopenharmony_ci if len(flowstr) == 0: 76662306a36Sopenharmony_ci return flowstr, k, m 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci flowstr = flowstr[strspn(flowstr, "), ") :] 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci return flowstr, k, m 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci def dpstr(self, masked=None, more=False): 77362306a36Sopenharmony_ci outstr = self.proto_str + "(" 77462306a36Sopenharmony_ci first = False 77562306a36Sopenharmony_ci for f in self.fields_map: 77662306a36Sopenharmony_ci if first: 77762306a36Sopenharmony_ci outstr += "," 77862306a36Sopenharmony_ci if masked is None: 77962306a36Sopenharmony_ci outstr += "%s=" % f[0] 78062306a36Sopenharmony_ci if isinstance(f[2], str): 78162306a36Sopenharmony_ci outstr += f[2] % self[f[1]] 78262306a36Sopenharmony_ci else: 78362306a36Sopenharmony_ci outstr += f[2](self[f[1]]) 78462306a36Sopenharmony_ci first = True 78562306a36Sopenharmony_ci elif more or f[3](masked[f[1]]) != 0: 78662306a36Sopenharmony_ci outstr += "%s=" % f[0] 78762306a36Sopenharmony_ci if isinstance(f[2], str): 78862306a36Sopenharmony_ci outstr += f[2] % self[f[1]] 78962306a36Sopenharmony_ci else: 79062306a36Sopenharmony_ci outstr += f[2](self[f[1]]) 79162306a36Sopenharmony_ci outstr += "/" 79262306a36Sopenharmony_ci if isinstance(f[2], str): 79362306a36Sopenharmony_ci outstr += f[2] % masked[f[1]] 79462306a36Sopenharmony_ci else: 79562306a36Sopenharmony_ci outstr += f[2](masked[f[1]]) 79662306a36Sopenharmony_ci first = True 79762306a36Sopenharmony_ci outstr += ")" 79862306a36Sopenharmony_ci return outstr 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci class ethaddr(ovs_key_proto): 80162306a36Sopenharmony_ci fields = ( 80262306a36Sopenharmony_ci ("src", "!6s"), 80362306a36Sopenharmony_ci ("dst", "!6s"), 80462306a36Sopenharmony_ci ) 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci fields_map = ( 80762306a36Sopenharmony_ci ( 80862306a36Sopenharmony_ci "src", 80962306a36Sopenharmony_ci "src", 81062306a36Sopenharmony_ci macstr, 81162306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 81262306a36Sopenharmony_ci convert_mac, 81362306a36Sopenharmony_ci ), 81462306a36Sopenharmony_ci ( 81562306a36Sopenharmony_ci "dst", 81662306a36Sopenharmony_ci "dst", 81762306a36Sopenharmony_ci macstr, 81862306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 81962306a36Sopenharmony_ci convert_mac, 82062306a36Sopenharmony_ci ), 82162306a36Sopenharmony_ci ) 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci def __init__( 82462306a36Sopenharmony_ci self, 82562306a36Sopenharmony_ci data=None, 82662306a36Sopenharmony_ci offset=None, 82762306a36Sopenharmony_ci parent=None, 82862306a36Sopenharmony_ci length=None, 82962306a36Sopenharmony_ci init=None, 83062306a36Sopenharmony_ci ): 83162306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 83262306a36Sopenharmony_ci self, 83362306a36Sopenharmony_ci "eth", 83462306a36Sopenharmony_ci data=data, 83562306a36Sopenharmony_ci offset=offset, 83662306a36Sopenharmony_ci parent=parent, 83762306a36Sopenharmony_ci length=length, 83862306a36Sopenharmony_ci init=init, 83962306a36Sopenharmony_ci ) 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci class ovs_key_ipv4(ovs_key_proto): 84262306a36Sopenharmony_ci fields = ( 84362306a36Sopenharmony_ci ("src", "!I"), 84462306a36Sopenharmony_ci ("dst", "!I"), 84562306a36Sopenharmony_ci ("proto", "B"), 84662306a36Sopenharmony_ci ("tos", "B"), 84762306a36Sopenharmony_ci ("ttl", "B"), 84862306a36Sopenharmony_ci ("frag", "B"), 84962306a36Sopenharmony_ci ) 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci fields_map = ( 85262306a36Sopenharmony_ci ( 85362306a36Sopenharmony_ci "src", 85462306a36Sopenharmony_ci "src", 85562306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 85662306a36Sopenharmony_ci int, 85762306a36Sopenharmony_ci convert_ipv4, 85862306a36Sopenharmony_ci ), 85962306a36Sopenharmony_ci ( 86062306a36Sopenharmony_ci "dst", 86162306a36Sopenharmony_ci "dst", 86262306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 86362306a36Sopenharmony_ci int, 86462306a36Sopenharmony_ci convert_ipv4, 86562306a36Sopenharmony_ci ), 86662306a36Sopenharmony_ci ("proto", "proto", "%d", lambda x: int(x) if x else 0, 86762306a36Sopenharmony_ci convert_int(8)), 86862306a36Sopenharmony_ci ("tos", "tos", "%d", lambda x: int(x) if x else 0, 86962306a36Sopenharmony_ci convert_int(8)), 87062306a36Sopenharmony_ci ("ttl", "ttl", "%d", lambda x: int(x) if x else 0, 87162306a36Sopenharmony_ci convert_int(8)), 87262306a36Sopenharmony_ci ("frag", "frag", "%d", lambda x: int(x) if x else 0, 87362306a36Sopenharmony_ci convert_int(8)), 87462306a36Sopenharmony_ci ) 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci def __init__( 87762306a36Sopenharmony_ci self, 87862306a36Sopenharmony_ci data=None, 87962306a36Sopenharmony_ci offset=None, 88062306a36Sopenharmony_ci parent=None, 88162306a36Sopenharmony_ci length=None, 88262306a36Sopenharmony_ci init=None, 88362306a36Sopenharmony_ci ): 88462306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 88562306a36Sopenharmony_ci self, 88662306a36Sopenharmony_ci "ipv4", 88762306a36Sopenharmony_ci data=data, 88862306a36Sopenharmony_ci offset=offset, 88962306a36Sopenharmony_ci parent=parent, 89062306a36Sopenharmony_ci length=length, 89162306a36Sopenharmony_ci init=init, 89262306a36Sopenharmony_ci ) 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci class ovs_key_ipv6(ovs_key_proto): 89562306a36Sopenharmony_ci fields = ( 89662306a36Sopenharmony_ci ("src", "!16s"), 89762306a36Sopenharmony_ci ("dst", "!16s"), 89862306a36Sopenharmony_ci ("label", "!I"), 89962306a36Sopenharmony_ci ("proto", "B"), 90062306a36Sopenharmony_ci ("tclass", "B"), 90162306a36Sopenharmony_ci ("hlimit", "B"), 90262306a36Sopenharmony_ci ("frag", "B"), 90362306a36Sopenharmony_ci ) 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci fields_map = ( 90662306a36Sopenharmony_ci ( 90762306a36Sopenharmony_ci "src", 90862306a36Sopenharmony_ci "src", 90962306a36Sopenharmony_ci lambda x: str(ipaddress.IPv6Address(x)), 91062306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 91162306a36Sopenharmony_ci lambda x: ipaddress.IPv6Address(x), 91262306a36Sopenharmony_ci ), 91362306a36Sopenharmony_ci ( 91462306a36Sopenharmony_ci "dst", 91562306a36Sopenharmony_ci "dst", 91662306a36Sopenharmony_ci lambda x: str(ipaddress.IPv6Address(x)), 91762306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 91862306a36Sopenharmony_ci lambda x: ipaddress.IPv6Address(x), 91962306a36Sopenharmony_ci ), 92062306a36Sopenharmony_ci ("label", "label", "%d", int), 92162306a36Sopenharmony_ci ("proto", "proto", "%d", int), 92262306a36Sopenharmony_ci ("tclass", "tclass", "%d", int), 92362306a36Sopenharmony_ci ("hlimit", "hlimit", "%d", int), 92462306a36Sopenharmony_ci ("frag", "frag", "%d", int), 92562306a36Sopenharmony_ci ) 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci def __init__( 92862306a36Sopenharmony_ci self, 92962306a36Sopenharmony_ci data=None, 93062306a36Sopenharmony_ci offset=None, 93162306a36Sopenharmony_ci parent=None, 93262306a36Sopenharmony_ci length=None, 93362306a36Sopenharmony_ci init=None, 93462306a36Sopenharmony_ci ): 93562306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 93662306a36Sopenharmony_ci self, 93762306a36Sopenharmony_ci "ipv6", 93862306a36Sopenharmony_ci data=data, 93962306a36Sopenharmony_ci offset=offset, 94062306a36Sopenharmony_ci parent=parent, 94162306a36Sopenharmony_ci length=length, 94262306a36Sopenharmony_ci init=init, 94362306a36Sopenharmony_ci ) 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci class ovs_key_tcp(ovs_key_proto): 94662306a36Sopenharmony_ci def __init__( 94762306a36Sopenharmony_ci self, 94862306a36Sopenharmony_ci data=None, 94962306a36Sopenharmony_ci offset=None, 95062306a36Sopenharmony_ci parent=None, 95162306a36Sopenharmony_ci length=None, 95262306a36Sopenharmony_ci init=None, 95362306a36Sopenharmony_ci ): 95462306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 95562306a36Sopenharmony_ci self, 95662306a36Sopenharmony_ci "tcp", 95762306a36Sopenharmony_ci data=data, 95862306a36Sopenharmony_ci offset=offset, 95962306a36Sopenharmony_ci parent=parent, 96062306a36Sopenharmony_ci length=length, 96162306a36Sopenharmony_ci init=init, 96262306a36Sopenharmony_ci ) 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci class ovs_key_udp(ovs_key_proto): 96562306a36Sopenharmony_ci def __init__( 96662306a36Sopenharmony_ci self, 96762306a36Sopenharmony_ci data=None, 96862306a36Sopenharmony_ci offset=None, 96962306a36Sopenharmony_ci parent=None, 97062306a36Sopenharmony_ci length=None, 97162306a36Sopenharmony_ci init=None, 97262306a36Sopenharmony_ci ): 97362306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 97462306a36Sopenharmony_ci self, 97562306a36Sopenharmony_ci "udp", 97662306a36Sopenharmony_ci data=data, 97762306a36Sopenharmony_ci offset=offset, 97862306a36Sopenharmony_ci parent=parent, 97962306a36Sopenharmony_ci length=length, 98062306a36Sopenharmony_ci init=init, 98162306a36Sopenharmony_ci ) 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci class ovs_key_sctp(ovs_key_proto): 98462306a36Sopenharmony_ci def __init__( 98562306a36Sopenharmony_ci self, 98662306a36Sopenharmony_ci data=None, 98762306a36Sopenharmony_ci offset=None, 98862306a36Sopenharmony_ci parent=None, 98962306a36Sopenharmony_ci length=None, 99062306a36Sopenharmony_ci init=None, 99162306a36Sopenharmony_ci ): 99262306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 99362306a36Sopenharmony_ci self, 99462306a36Sopenharmony_ci "sctp", 99562306a36Sopenharmony_ci data=data, 99662306a36Sopenharmony_ci offset=offset, 99762306a36Sopenharmony_ci parent=parent, 99862306a36Sopenharmony_ci length=length, 99962306a36Sopenharmony_ci init=init, 100062306a36Sopenharmony_ci ) 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci class ovs_key_icmp(ovs_key_proto): 100362306a36Sopenharmony_ci fields = ( 100462306a36Sopenharmony_ci ("type", "B"), 100562306a36Sopenharmony_ci ("code", "B"), 100662306a36Sopenharmony_ci ) 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci fields_map = ( 100962306a36Sopenharmony_ci ("type", "type", "%d", lambda x: int(x) if x else 0), 101062306a36Sopenharmony_ci ("code", "code", "%d", lambda x: int(x) if x else 0), 101162306a36Sopenharmony_ci ) 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci def __init__( 101462306a36Sopenharmony_ci self, 101562306a36Sopenharmony_ci data=None, 101662306a36Sopenharmony_ci offset=None, 101762306a36Sopenharmony_ci parent=None, 101862306a36Sopenharmony_ci length=None, 101962306a36Sopenharmony_ci init=None, 102062306a36Sopenharmony_ci ): 102162306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 102262306a36Sopenharmony_ci self, 102362306a36Sopenharmony_ci "icmp", 102462306a36Sopenharmony_ci data=data, 102562306a36Sopenharmony_ci offset=offset, 102662306a36Sopenharmony_ci parent=parent, 102762306a36Sopenharmony_ci length=length, 102862306a36Sopenharmony_ci init=init, 102962306a36Sopenharmony_ci ) 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci class ovs_key_icmpv6(ovs_key_icmp): 103262306a36Sopenharmony_ci def __init__( 103362306a36Sopenharmony_ci self, 103462306a36Sopenharmony_ci data=None, 103562306a36Sopenharmony_ci offset=None, 103662306a36Sopenharmony_ci parent=None, 103762306a36Sopenharmony_ci length=None, 103862306a36Sopenharmony_ci init=None, 103962306a36Sopenharmony_ci ): 104062306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 104162306a36Sopenharmony_ci self, 104262306a36Sopenharmony_ci "icmpv6", 104362306a36Sopenharmony_ci data=data, 104462306a36Sopenharmony_ci offset=offset, 104562306a36Sopenharmony_ci parent=parent, 104662306a36Sopenharmony_ci length=length, 104762306a36Sopenharmony_ci init=init, 104862306a36Sopenharmony_ci ) 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci class ovs_key_arp(ovs_key_proto): 105162306a36Sopenharmony_ci fields = ( 105262306a36Sopenharmony_ci ("sip", "!I"), 105362306a36Sopenharmony_ci ("tip", "!I"), 105462306a36Sopenharmony_ci ("op", "!H"), 105562306a36Sopenharmony_ci ("sha", "!6s"), 105662306a36Sopenharmony_ci ("tha", "!6s"), 105762306a36Sopenharmony_ci ("pad", "xx"), 105862306a36Sopenharmony_ci ) 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci fields_map = ( 106162306a36Sopenharmony_ci ( 106262306a36Sopenharmony_ci "sip", 106362306a36Sopenharmony_ci "sip", 106462306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 106562306a36Sopenharmony_ci int, 106662306a36Sopenharmony_ci convert_ipv4, 106762306a36Sopenharmony_ci ), 106862306a36Sopenharmony_ci ( 106962306a36Sopenharmony_ci "tip", 107062306a36Sopenharmony_ci "tip", 107162306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 107262306a36Sopenharmony_ci int, 107362306a36Sopenharmony_ci convert_ipv4, 107462306a36Sopenharmony_ci ), 107562306a36Sopenharmony_ci ("op", "op", "%d", lambda x: int(x) if x else 0), 107662306a36Sopenharmony_ci ( 107762306a36Sopenharmony_ci "sha", 107862306a36Sopenharmony_ci "sha", 107962306a36Sopenharmony_ci macstr, 108062306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 108162306a36Sopenharmony_ci convert_mac, 108262306a36Sopenharmony_ci ), 108362306a36Sopenharmony_ci ( 108462306a36Sopenharmony_ci "tha", 108562306a36Sopenharmony_ci "tha", 108662306a36Sopenharmony_ci macstr, 108762306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 108862306a36Sopenharmony_ci convert_mac, 108962306a36Sopenharmony_ci ), 109062306a36Sopenharmony_ci ) 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci def __init__( 109362306a36Sopenharmony_ci self, 109462306a36Sopenharmony_ci data=None, 109562306a36Sopenharmony_ci offset=None, 109662306a36Sopenharmony_ci parent=None, 109762306a36Sopenharmony_ci length=None, 109862306a36Sopenharmony_ci init=None, 109962306a36Sopenharmony_ci ): 110062306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 110162306a36Sopenharmony_ci self, 110262306a36Sopenharmony_ci "arp", 110362306a36Sopenharmony_ci data=data, 110462306a36Sopenharmony_ci offset=offset, 110562306a36Sopenharmony_ci parent=parent, 110662306a36Sopenharmony_ci length=length, 110762306a36Sopenharmony_ci init=init, 110862306a36Sopenharmony_ci ) 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci class ovs_key_nd(ovs_key_proto): 111162306a36Sopenharmony_ci fields = ( 111262306a36Sopenharmony_ci ("target", "!16s"), 111362306a36Sopenharmony_ci ("sll", "!6s"), 111462306a36Sopenharmony_ci ("tll", "!6s"), 111562306a36Sopenharmony_ci ) 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci fields_map = ( 111862306a36Sopenharmony_ci ( 111962306a36Sopenharmony_ci "target", 112062306a36Sopenharmony_ci "target", 112162306a36Sopenharmony_ci lambda x: str(ipaddress.IPv6Address(x)), 112262306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 112362306a36Sopenharmony_ci ), 112462306a36Sopenharmony_ci ("sll", "sll", macstr, lambda x: int.from_bytes(x, "big")), 112562306a36Sopenharmony_ci ("tll", "tll", macstr, lambda x: int.from_bytes(x, "big")), 112662306a36Sopenharmony_ci ) 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci def __init__( 112962306a36Sopenharmony_ci self, 113062306a36Sopenharmony_ci data=None, 113162306a36Sopenharmony_ci offset=None, 113262306a36Sopenharmony_ci parent=None, 113362306a36Sopenharmony_ci length=None, 113462306a36Sopenharmony_ci init=None, 113562306a36Sopenharmony_ci ): 113662306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 113762306a36Sopenharmony_ci self, 113862306a36Sopenharmony_ci "nd", 113962306a36Sopenharmony_ci data=data, 114062306a36Sopenharmony_ci offset=offset, 114162306a36Sopenharmony_ci parent=parent, 114262306a36Sopenharmony_ci length=length, 114362306a36Sopenharmony_ci init=init, 114462306a36Sopenharmony_ci ) 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci class ovs_key_ct_tuple_ipv4(ovs_key_proto): 114762306a36Sopenharmony_ci fields = ( 114862306a36Sopenharmony_ci ("src", "!I"), 114962306a36Sopenharmony_ci ("dst", "!I"), 115062306a36Sopenharmony_ci ("tp_src", "!H"), 115162306a36Sopenharmony_ci ("tp_dst", "!H"), 115262306a36Sopenharmony_ci ("proto", "B"), 115362306a36Sopenharmony_ci ) 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci fields_map = ( 115662306a36Sopenharmony_ci ( 115762306a36Sopenharmony_ci "src", 115862306a36Sopenharmony_ci "src", 115962306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 116062306a36Sopenharmony_ci int, 116162306a36Sopenharmony_ci convert_ipv4, 116262306a36Sopenharmony_ci ), 116362306a36Sopenharmony_ci ( 116462306a36Sopenharmony_ci "dst", 116562306a36Sopenharmony_ci "dst", 116662306a36Sopenharmony_ci lambda x: str(ipaddress.IPv4Address(x)), 116762306a36Sopenharmony_ci int, 116862306a36Sopenharmony_ci convert_ipv4, 116962306a36Sopenharmony_ci ), 117062306a36Sopenharmony_ci ("tp_src", "tp_src", "%d", int), 117162306a36Sopenharmony_ci ("tp_dst", "tp_dst", "%d", int), 117262306a36Sopenharmony_ci ("proto", "proto", "%d", int), 117362306a36Sopenharmony_ci ) 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci def __init__( 117662306a36Sopenharmony_ci self, 117762306a36Sopenharmony_ci data=None, 117862306a36Sopenharmony_ci offset=None, 117962306a36Sopenharmony_ci parent=None, 118062306a36Sopenharmony_ci length=None, 118162306a36Sopenharmony_ci init=None, 118262306a36Sopenharmony_ci ): 118362306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 118462306a36Sopenharmony_ci self, 118562306a36Sopenharmony_ci "ct_tuple4", 118662306a36Sopenharmony_ci data=data, 118762306a36Sopenharmony_ci offset=offset, 118862306a36Sopenharmony_ci parent=parent, 118962306a36Sopenharmony_ci length=length, 119062306a36Sopenharmony_ci init=init, 119162306a36Sopenharmony_ci ) 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_ci class ovs_key_ct_tuple_ipv6(nla): 119462306a36Sopenharmony_ci fields = ( 119562306a36Sopenharmony_ci ("src", "!16s"), 119662306a36Sopenharmony_ci ("dst", "!16s"), 119762306a36Sopenharmony_ci ("tp_src", "!H"), 119862306a36Sopenharmony_ci ("tp_dst", "!H"), 119962306a36Sopenharmony_ci ("proto", "B"), 120062306a36Sopenharmony_ci ) 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci fields_map = ( 120362306a36Sopenharmony_ci ( 120462306a36Sopenharmony_ci "src", 120562306a36Sopenharmony_ci "src", 120662306a36Sopenharmony_ci lambda x: str(ipaddress.IPv6Address(x)), 120762306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big", convertmac), 120862306a36Sopenharmony_ci ), 120962306a36Sopenharmony_ci ( 121062306a36Sopenharmony_ci "dst", 121162306a36Sopenharmony_ci "dst", 121262306a36Sopenharmony_ci lambda x: str(ipaddress.IPv6Address(x)), 121362306a36Sopenharmony_ci lambda x: int.from_bytes(x, "big"), 121462306a36Sopenharmony_ci ), 121562306a36Sopenharmony_ci ("tp_src", "tp_src", "%d", int), 121662306a36Sopenharmony_ci ("tp_dst", "tp_dst", "%d", int), 121762306a36Sopenharmony_ci ("proto", "proto", "%d", int), 121862306a36Sopenharmony_ci ) 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci def __init__( 122162306a36Sopenharmony_ci self, 122262306a36Sopenharmony_ci data=None, 122362306a36Sopenharmony_ci offset=None, 122462306a36Sopenharmony_ci parent=None, 122562306a36Sopenharmony_ci length=None, 122662306a36Sopenharmony_ci init=None, 122762306a36Sopenharmony_ci ): 122862306a36Sopenharmony_ci ovskey.ovs_key_proto.__init__( 122962306a36Sopenharmony_ci self, 123062306a36Sopenharmony_ci "ct_tuple6", 123162306a36Sopenharmony_ci data=data, 123262306a36Sopenharmony_ci offset=offset, 123362306a36Sopenharmony_ci parent=parent, 123462306a36Sopenharmony_ci length=length, 123562306a36Sopenharmony_ci init=init, 123662306a36Sopenharmony_ci ) 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci class ovs_key_mpls(nla): 123962306a36Sopenharmony_ci fields = (("lse", ">I"),) 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci def parse(self, flowstr, mask=None): 124262306a36Sopenharmony_ci for field in ( 124362306a36Sopenharmony_ci ("OVS_KEY_ATTR_PRIORITY", "skb_priority", intparse), 124462306a36Sopenharmony_ci ("OVS_KEY_ATTR_SKB_MARK", "skb_mark", intparse), 124562306a36Sopenharmony_ci ("OVS_KEY_ATTR_RECIRC_ID", "recirc_id", intparse), 124662306a36Sopenharmony_ci ("OVS_KEY_ATTR_DP_HASH", "dp_hash", intparse), 124762306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_STATE", "ct_state", parse_ct_state), 124862306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_ZONE", "ct_zone", intparse), 124962306a36Sopenharmony_ci ("OVS_KEY_ATTR_CT_MARK", "ct_mark", intparse), 125062306a36Sopenharmony_ci ("OVS_KEY_ATTR_IN_PORT", "in_port", intparse), 125162306a36Sopenharmony_ci ( 125262306a36Sopenharmony_ci "OVS_KEY_ATTR_ETHERNET", 125362306a36Sopenharmony_ci "eth", 125462306a36Sopenharmony_ci ovskey.ethaddr, 125562306a36Sopenharmony_ci ), 125662306a36Sopenharmony_ci ( 125762306a36Sopenharmony_ci "OVS_KEY_ATTR_ETHERTYPE", 125862306a36Sopenharmony_ci "eth_type", 125962306a36Sopenharmony_ci lambda x: intparse(x, "0xffff"), 126062306a36Sopenharmony_ci ), 126162306a36Sopenharmony_ci ( 126262306a36Sopenharmony_ci "OVS_KEY_ATTR_IPV4", 126362306a36Sopenharmony_ci "ipv4", 126462306a36Sopenharmony_ci ovskey.ovs_key_ipv4, 126562306a36Sopenharmony_ci ), 126662306a36Sopenharmony_ci ( 126762306a36Sopenharmony_ci "OVS_KEY_ATTR_IPV6", 126862306a36Sopenharmony_ci "ipv6", 126962306a36Sopenharmony_ci ovskey.ovs_key_ipv6, 127062306a36Sopenharmony_ci ), 127162306a36Sopenharmony_ci ( 127262306a36Sopenharmony_ci "OVS_KEY_ATTR_ARP", 127362306a36Sopenharmony_ci "arp", 127462306a36Sopenharmony_ci ovskey.ovs_key_arp, 127562306a36Sopenharmony_ci ), 127662306a36Sopenharmony_ci ( 127762306a36Sopenharmony_ci "OVS_KEY_ATTR_TCP", 127862306a36Sopenharmony_ci "tcp", 127962306a36Sopenharmony_ci ovskey.ovs_key_tcp, 128062306a36Sopenharmony_ci ), 128162306a36Sopenharmony_ci ( 128262306a36Sopenharmony_ci "OVS_KEY_ATTR_UDP", 128362306a36Sopenharmony_ci "udp", 128462306a36Sopenharmony_ci ovskey.ovs_key_udp, 128562306a36Sopenharmony_ci ), 128662306a36Sopenharmony_ci ( 128762306a36Sopenharmony_ci "OVS_KEY_ATTR_ICMP", 128862306a36Sopenharmony_ci "icmp", 128962306a36Sopenharmony_ci ovskey.ovs_key_icmp, 129062306a36Sopenharmony_ci ), 129162306a36Sopenharmony_ci ( 129262306a36Sopenharmony_ci "OVS_KEY_ATTR_TCP_FLAGS", 129362306a36Sopenharmony_ci "tcp_flags", 129462306a36Sopenharmony_ci lambda x: parse_flags(x, None), 129562306a36Sopenharmony_ci ), 129662306a36Sopenharmony_ci ): 129762306a36Sopenharmony_ci fld = field[1] + "(" 129862306a36Sopenharmony_ci if not flowstr.startswith(fld): 129962306a36Sopenharmony_ci continue 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci if not isinstance(field[2], types.FunctionType): 130262306a36Sopenharmony_ci nk = field[2]() 130362306a36Sopenharmony_ci flowstr, k, m = nk.parse(flowstr, field[2]) 130462306a36Sopenharmony_ci else: 130562306a36Sopenharmony_ci flowstr = flowstr[len(fld) :] 130662306a36Sopenharmony_ci flowstr, k, m = field[2](flowstr) 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if m and mask is not None: 130962306a36Sopenharmony_ci mask["attrs"].append([field[0], m]) 131062306a36Sopenharmony_ci self["attrs"].append([field[0], k]) 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci flowstr = flowstr[strspn(flowstr, "),") :] 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci return flowstr 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci def dpstr(self, mask=None, more=False): 131762306a36Sopenharmony_ci print_str = "" 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci for field in ( 132062306a36Sopenharmony_ci ( 132162306a36Sopenharmony_ci "OVS_KEY_ATTR_PRIORITY", 132262306a36Sopenharmony_ci "skb_priority", 132362306a36Sopenharmony_ci "%d", 132462306a36Sopenharmony_ci lambda x: False, 132562306a36Sopenharmony_ci True, 132662306a36Sopenharmony_ci ), 132762306a36Sopenharmony_ci ( 132862306a36Sopenharmony_ci "OVS_KEY_ATTR_SKB_MARK", 132962306a36Sopenharmony_ci "skb_mark", 133062306a36Sopenharmony_ci "%d", 133162306a36Sopenharmony_ci lambda x: False, 133262306a36Sopenharmony_ci True, 133362306a36Sopenharmony_ci ), 133462306a36Sopenharmony_ci ( 133562306a36Sopenharmony_ci "OVS_KEY_ATTR_RECIRC_ID", 133662306a36Sopenharmony_ci "recirc_id", 133762306a36Sopenharmony_ci "0x%08X", 133862306a36Sopenharmony_ci lambda x: False, 133962306a36Sopenharmony_ci True, 134062306a36Sopenharmony_ci ), 134162306a36Sopenharmony_ci ( 134262306a36Sopenharmony_ci "OVS_KEY_ATTR_DP_HASH", 134362306a36Sopenharmony_ci "dp_hash", 134462306a36Sopenharmony_ci "0x%08X", 134562306a36Sopenharmony_ci lambda x: False, 134662306a36Sopenharmony_ci True, 134762306a36Sopenharmony_ci ), 134862306a36Sopenharmony_ci ( 134962306a36Sopenharmony_ci "OVS_KEY_ATTR_CT_STATE", 135062306a36Sopenharmony_ci "ct_state", 135162306a36Sopenharmony_ci "0x%04x", 135262306a36Sopenharmony_ci lambda x: False, 135362306a36Sopenharmony_ci True, 135462306a36Sopenharmony_ci ), 135562306a36Sopenharmony_ci ( 135662306a36Sopenharmony_ci "OVS_KEY_ATTR_CT_ZONE", 135762306a36Sopenharmony_ci "ct_zone", 135862306a36Sopenharmony_ci "0x%04x", 135962306a36Sopenharmony_ci lambda x: False, 136062306a36Sopenharmony_ci True, 136162306a36Sopenharmony_ci ), 136262306a36Sopenharmony_ci ( 136362306a36Sopenharmony_ci "OVS_KEY_ATTR_CT_MARK", 136462306a36Sopenharmony_ci "ct_mark", 136562306a36Sopenharmony_ci "0x%08x", 136662306a36Sopenharmony_ci lambda x: False, 136762306a36Sopenharmony_ci True, 136862306a36Sopenharmony_ci ), 136962306a36Sopenharmony_ci ( 137062306a36Sopenharmony_ci "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", 137162306a36Sopenharmony_ci None, 137262306a36Sopenharmony_ci None, 137362306a36Sopenharmony_ci False, 137462306a36Sopenharmony_ci False, 137562306a36Sopenharmony_ci ), 137662306a36Sopenharmony_ci ( 137762306a36Sopenharmony_ci "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", 137862306a36Sopenharmony_ci None, 137962306a36Sopenharmony_ci None, 138062306a36Sopenharmony_ci False, 138162306a36Sopenharmony_ci False, 138262306a36Sopenharmony_ci ), 138362306a36Sopenharmony_ci ( 138462306a36Sopenharmony_ci "OVS_KEY_ATTR_IN_PORT", 138562306a36Sopenharmony_ci "in_port", 138662306a36Sopenharmony_ci "%d", 138762306a36Sopenharmony_ci lambda x: True, 138862306a36Sopenharmony_ci True, 138962306a36Sopenharmony_ci ), 139062306a36Sopenharmony_ci ("OVS_KEY_ATTR_ETHERNET", None, None, False, False), 139162306a36Sopenharmony_ci ( 139262306a36Sopenharmony_ci "OVS_KEY_ATTR_ETHERTYPE", 139362306a36Sopenharmony_ci "eth_type", 139462306a36Sopenharmony_ci "0x%04x", 139562306a36Sopenharmony_ci lambda x: int(x) == 0xFFFF, 139662306a36Sopenharmony_ci True, 139762306a36Sopenharmony_ci ), 139862306a36Sopenharmony_ci ("OVS_KEY_ATTR_IPV4", None, None, False, False), 139962306a36Sopenharmony_ci ("OVS_KEY_ATTR_IPV6", None, None, False, False), 140062306a36Sopenharmony_ci ("OVS_KEY_ATTR_ARP", None, None, False, False), 140162306a36Sopenharmony_ci ("OVS_KEY_ATTR_TCP", None, None, False, False), 140262306a36Sopenharmony_ci ( 140362306a36Sopenharmony_ci "OVS_KEY_ATTR_TCP_FLAGS", 140462306a36Sopenharmony_ci "tcp_flags", 140562306a36Sopenharmony_ci "0x%04x", 140662306a36Sopenharmony_ci lambda x: False, 140762306a36Sopenharmony_ci True, 140862306a36Sopenharmony_ci ), 140962306a36Sopenharmony_ci ("OVS_KEY_ATTR_UDP", None, None, False, False), 141062306a36Sopenharmony_ci ("OVS_KEY_ATTR_SCTP", None, None, False, False), 141162306a36Sopenharmony_ci ("OVS_KEY_ATTR_ICMP", None, None, False, False), 141262306a36Sopenharmony_ci ("OVS_KEY_ATTR_ICMPV6", None, None, False, False), 141362306a36Sopenharmony_ci ("OVS_KEY_ATTR_ND", None, None, False, False), 141462306a36Sopenharmony_ci ): 141562306a36Sopenharmony_ci v = self.get_attr(field[0]) 141662306a36Sopenharmony_ci if v is not None: 141762306a36Sopenharmony_ci m = None if mask is None else mask.get_attr(field[0]) 141862306a36Sopenharmony_ci if field[4] is False: 141962306a36Sopenharmony_ci print_str += v.dpstr(m, more) 142062306a36Sopenharmony_ci print_str += "," 142162306a36Sopenharmony_ci else: 142262306a36Sopenharmony_ci if m is None or field[3](m): 142362306a36Sopenharmony_ci print_str += field[1] + "(" 142462306a36Sopenharmony_ci print_str += field[2] % v 142562306a36Sopenharmony_ci print_str += ")," 142662306a36Sopenharmony_ci elif more or m != 0: 142762306a36Sopenharmony_ci print_str += field[1] + "(" 142862306a36Sopenharmony_ci print_str += (field[2] % v) + "/" + (field[2] % m) 142962306a36Sopenharmony_ci print_str += ")," 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci return print_str 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ciclass OvsPacket(GenericNetlinkSocket): 143562306a36Sopenharmony_ci OVS_PACKET_CMD_MISS = 1 # Flow table miss 143662306a36Sopenharmony_ci OVS_PACKET_CMD_ACTION = 2 # USERSPACE action 143762306a36Sopenharmony_ci OVS_PACKET_CMD_EXECUTE = 3 # Apply actions to packet 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci class ovs_packet_msg(ovs_dp_msg): 144062306a36Sopenharmony_ci nla_map = ( 144162306a36Sopenharmony_ci ("OVS_PACKET_ATTR_UNSPEC", "none"), 144262306a36Sopenharmony_ci ("OVS_PACKET_ATTR_PACKET", "array(uint8)"), 144362306a36Sopenharmony_ci ("OVS_PACKET_ATTR_KEY", "ovskey"), 144462306a36Sopenharmony_ci ("OVS_PACKET_ATTR_ACTIONS", "ovsactions"), 144562306a36Sopenharmony_ci ("OVS_PACKET_ATTR_USERDATA", "none"), 144662306a36Sopenharmony_ci ("OVS_PACKET_ATTR_EGRESS_TUN_KEY", "none"), 144762306a36Sopenharmony_ci ("OVS_PACKET_ATTR_UNUSED1", "none"), 144862306a36Sopenharmony_ci ("OVS_PACKET_ATTR_UNUSED2", "none"), 144962306a36Sopenharmony_ci ("OVS_PACKET_ATTR_PROBE", "none"), 145062306a36Sopenharmony_ci ("OVS_PACKET_ATTR_MRU", "uint16"), 145162306a36Sopenharmony_ci ("OVS_PACKET_ATTR_LEN", "uint32"), 145262306a36Sopenharmony_ci ("OVS_PACKET_ATTR_HASH", "uint64"), 145362306a36Sopenharmony_ci ) 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci def __init__(self): 145662306a36Sopenharmony_ci GenericNetlinkSocket.__init__(self) 145762306a36Sopenharmony_ci self.bind(OVS_PACKET_FAMILY, OvsPacket.ovs_packet_msg) 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci def upcall_handler(self, up=None): 146062306a36Sopenharmony_ci print("listening on upcall packet handler:", self.epid) 146162306a36Sopenharmony_ci while True: 146262306a36Sopenharmony_ci try: 146362306a36Sopenharmony_ci msgs = self.get() 146462306a36Sopenharmony_ci for msg in msgs: 146562306a36Sopenharmony_ci if not up: 146662306a36Sopenharmony_ci continue 146762306a36Sopenharmony_ci if msg["cmd"] == OvsPacket.OVS_PACKET_CMD_MISS: 146862306a36Sopenharmony_ci up.miss(msg) 146962306a36Sopenharmony_ci elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_ACTION: 147062306a36Sopenharmony_ci up.action(msg) 147162306a36Sopenharmony_ci elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_EXECUTE: 147262306a36Sopenharmony_ci up.execute(msg) 147362306a36Sopenharmony_ci else: 147462306a36Sopenharmony_ci print("Unkonwn cmd: %d" % msg["cmd"]) 147562306a36Sopenharmony_ci except NetlinkError as ne: 147662306a36Sopenharmony_ci raise ne 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ciclass OvsDatapath(GenericNetlinkSocket): 148062306a36Sopenharmony_ci OVS_DP_F_VPORT_PIDS = 1 << 1 148162306a36Sopenharmony_ci OVS_DP_F_DISPATCH_UPCALL_PER_CPU = 1 << 3 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci class dp_cmd_msg(ovs_dp_msg): 148462306a36Sopenharmony_ci """ 148562306a36Sopenharmony_ci Message class that will be used to communicate with the kernel module. 148662306a36Sopenharmony_ci """ 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci nla_map = ( 148962306a36Sopenharmony_ci ("OVS_DP_ATTR_UNSPEC", "none"), 149062306a36Sopenharmony_ci ("OVS_DP_ATTR_NAME", "asciiz"), 149162306a36Sopenharmony_ci ("OVS_DP_ATTR_UPCALL_PID", "array(uint32)"), 149262306a36Sopenharmony_ci ("OVS_DP_ATTR_STATS", "dpstats"), 149362306a36Sopenharmony_ci ("OVS_DP_ATTR_MEGAFLOW_STATS", "megaflowstats"), 149462306a36Sopenharmony_ci ("OVS_DP_ATTR_USER_FEATURES", "uint32"), 149562306a36Sopenharmony_ci ("OVS_DP_ATTR_PAD", "none"), 149662306a36Sopenharmony_ci ("OVS_DP_ATTR_MASKS_CACHE_SIZE", "uint32"), 149762306a36Sopenharmony_ci ("OVS_DP_ATTR_PER_CPU_PIDS", "array(uint32)"), 149862306a36Sopenharmony_ci ) 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci class dpstats(nla): 150162306a36Sopenharmony_ci fields = ( 150262306a36Sopenharmony_ci ("hit", "=Q"), 150362306a36Sopenharmony_ci ("missed", "=Q"), 150462306a36Sopenharmony_ci ("lost", "=Q"), 150562306a36Sopenharmony_ci ("flows", "=Q"), 150662306a36Sopenharmony_ci ) 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci class megaflowstats(nla): 150962306a36Sopenharmony_ci fields = ( 151062306a36Sopenharmony_ci ("mask_hit", "=Q"), 151162306a36Sopenharmony_ci ("masks", "=I"), 151262306a36Sopenharmony_ci ("padding", "=I"), 151362306a36Sopenharmony_ci ("cache_hits", "=Q"), 151462306a36Sopenharmony_ci ("pad1", "=Q"), 151562306a36Sopenharmony_ci ) 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci def __init__(self): 151862306a36Sopenharmony_ci GenericNetlinkSocket.__init__(self) 151962306a36Sopenharmony_ci self.bind(OVS_DATAPATH_FAMILY, OvsDatapath.dp_cmd_msg) 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci def info(self, dpname, ifindex=0): 152262306a36Sopenharmony_ci msg = OvsDatapath.dp_cmd_msg() 152362306a36Sopenharmony_ci msg["cmd"] = OVS_DP_CMD_GET 152462306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 152562306a36Sopenharmony_ci msg["reserved"] = 0 152662306a36Sopenharmony_ci msg["dpifindex"] = ifindex 152762306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci try: 153062306a36Sopenharmony_ci reply = self.nlm_request( 153162306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST 153262306a36Sopenharmony_ci ) 153362306a36Sopenharmony_ci reply = reply[0] 153462306a36Sopenharmony_ci except NetlinkError as ne: 153562306a36Sopenharmony_ci if ne.code == errno.ENODEV: 153662306a36Sopenharmony_ci reply = None 153762306a36Sopenharmony_ci else: 153862306a36Sopenharmony_ci raise ne 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci return reply 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci def create( 154362306a36Sopenharmony_ci self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket() 154462306a36Sopenharmony_ci ): 154562306a36Sopenharmony_ci msg = OvsDatapath.dp_cmd_msg() 154662306a36Sopenharmony_ci msg["cmd"] = OVS_DP_CMD_NEW 154762306a36Sopenharmony_ci if versionStr is None: 154862306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 154962306a36Sopenharmony_ci else: 155062306a36Sopenharmony_ci msg["version"] = int(versionStr.split(":")[0], 0) 155162306a36Sopenharmony_ci msg["reserved"] = 0 155262306a36Sopenharmony_ci msg["dpifindex"] = 0 155362306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci dpfeatures = 0 155662306a36Sopenharmony_ci if versionStr is not None and versionStr.find(":") != -1: 155762306a36Sopenharmony_ci dpfeatures = int(versionStr.split(":")[1], 0) 155862306a36Sopenharmony_ci else: 155962306a36Sopenharmony_ci if versionStr is None or versionStr.find(":") == -1: 156062306a36Sopenharmony_ci dpfeatures |= OvsDatapath.OVS_DP_F_DISPATCH_UPCALL_PER_CPU 156162306a36Sopenharmony_ci dpfeatures &= ~OvsDatapath.OVS_DP_F_VPORT_PIDS 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci nproc = multiprocessing.cpu_count() 156462306a36Sopenharmony_ci procarray = [] 156562306a36Sopenharmony_ci for i in range(1, nproc): 156662306a36Sopenharmony_ci procarray += [int(p.epid)] 156762306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", procarray]) 156862306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) 156962306a36Sopenharmony_ci if not shouldUpcall: 157062306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", [0]]) 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci try: 157362306a36Sopenharmony_ci reply = self.nlm_request( 157462306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 157562306a36Sopenharmony_ci ) 157662306a36Sopenharmony_ci reply = reply[0] 157762306a36Sopenharmony_ci except NetlinkError as ne: 157862306a36Sopenharmony_ci if ne.code == errno.EEXIST: 157962306a36Sopenharmony_ci reply = None 158062306a36Sopenharmony_ci else: 158162306a36Sopenharmony_ci raise ne 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci return reply 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci def destroy(self, dpname): 158662306a36Sopenharmony_ci msg = OvsDatapath.dp_cmd_msg() 158762306a36Sopenharmony_ci msg["cmd"] = OVS_DP_CMD_DEL 158862306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 158962306a36Sopenharmony_ci msg["reserved"] = 0 159062306a36Sopenharmony_ci msg["dpifindex"] = 0 159162306a36Sopenharmony_ci msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci try: 159462306a36Sopenharmony_ci reply = self.nlm_request( 159562306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 159662306a36Sopenharmony_ci ) 159762306a36Sopenharmony_ci reply = reply[0] 159862306a36Sopenharmony_ci except NetlinkError as ne: 159962306a36Sopenharmony_ci if ne.code == errno.ENODEV: 160062306a36Sopenharmony_ci reply = None 160162306a36Sopenharmony_ci else: 160262306a36Sopenharmony_ci raise ne 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci return reply 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ciclass OvsVport(GenericNetlinkSocket): 160862306a36Sopenharmony_ci OVS_VPORT_TYPE_NETDEV = 1 160962306a36Sopenharmony_ci OVS_VPORT_TYPE_INTERNAL = 2 161062306a36Sopenharmony_ci OVS_VPORT_TYPE_GRE = 3 161162306a36Sopenharmony_ci OVS_VPORT_TYPE_VXLAN = 4 161262306a36Sopenharmony_ci OVS_VPORT_TYPE_GENEVE = 5 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci class ovs_vport_msg(ovs_dp_msg): 161562306a36Sopenharmony_ci nla_map = ( 161662306a36Sopenharmony_ci ("OVS_VPORT_ATTR_UNSPEC", "none"), 161762306a36Sopenharmony_ci ("OVS_VPORT_ATTR_PORT_NO", "uint32"), 161862306a36Sopenharmony_ci ("OVS_VPORT_ATTR_TYPE", "uint32"), 161962306a36Sopenharmony_ci ("OVS_VPORT_ATTR_NAME", "asciiz"), 162062306a36Sopenharmony_ci ("OVS_VPORT_ATTR_OPTIONS", "none"), 162162306a36Sopenharmony_ci ("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"), 162262306a36Sopenharmony_ci ("OVS_VPORT_ATTR_STATS", "vportstats"), 162362306a36Sopenharmony_ci ("OVS_VPORT_ATTR_PAD", "none"), 162462306a36Sopenharmony_ci ("OVS_VPORT_ATTR_IFINDEX", "uint32"), 162562306a36Sopenharmony_ci ("OVS_VPORT_ATTR_NETNSID", "uint32"), 162662306a36Sopenharmony_ci ) 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci class vportstats(nla): 162962306a36Sopenharmony_ci fields = ( 163062306a36Sopenharmony_ci ("rx_packets", "=Q"), 163162306a36Sopenharmony_ci ("tx_packets", "=Q"), 163262306a36Sopenharmony_ci ("rx_bytes", "=Q"), 163362306a36Sopenharmony_ci ("tx_bytes", "=Q"), 163462306a36Sopenharmony_ci ("rx_errors", "=Q"), 163562306a36Sopenharmony_ci ("tx_errors", "=Q"), 163662306a36Sopenharmony_ci ("rx_dropped", "=Q"), 163762306a36Sopenharmony_ci ("tx_dropped", "=Q"), 163862306a36Sopenharmony_ci ) 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci def type_to_str(vport_type): 164162306a36Sopenharmony_ci if vport_type == OvsVport.OVS_VPORT_TYPE_NETDEV: 164262306a36Sopenharmony_ci return "netdev" 164362306a36Sopenharmony_ci elif vport_type == OvsVport.OVS_VPORT_TYPE_INTERNAL: 164462306a36Sopenharmony_ci return "internal" 164562306a36Sopenharmony_ci elif vport_type == OvsVport.OVS_VPORT_TYPE_GRE: 164662306a36Sopenharmony_ci return "gre" 164762306a36Sopenharmony_ci elif vport_type == OvsVport.OVS_VPORT_TYPE_VXLAN: 164862306a36Sopenharmony_ci return "vxlan" 164962306a36Sopenharmony_ci elif vport_type == OvsVport.OVS_VPORT_TYPE_GENEVE: 165062306a36Sopenharmony_ci return "geneve" 165162306a36Sopenharmony_ci raise ValueError("Unknown vport type:%d" % vport_type) 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci def str_to_type(vport_type): 165462306a36Sopenharmony_ci if vport_type == "netdev": 165562306a36Sopenharmony_ci return OvsVport.OVS_VPORT_TYPE_NETDEV 165662306a36Sopenharmony_ci elif vport_type == "internal": 165762306a36Sopenharmony_ci return OvsVport.OVS_VPORT_TYPE_INTERNAL 165862306a36Sopenharmony_ci elif vport_type == "gre": 165962306a36Sopenharmony_ci return OvsVport.OVS_VPORT_TYPE_INTERNAL 166062306a36Sopenharmony_ci elif vport_type == "vxlan": 166162306a36Sopenharmony_ci return OvsVport.OVS_VPORT_TYPE_VXLAN 166262306a36Sopenharmony_ci elif vport_type == "geneve": 166362306a36Sopenharmony_ci return OvsVport.OVS_VPORT_TYPE_GENEVE 166462306a36Sopenharmony_ci raise ValueError("Unknown vport type: '%s'" % vport_type) 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci def __init__(self, packet=OvsPacket()): 166762306a36Sopenharmony_ci GenericNetlinkSocket.__init__(self) 166862306a36Sopenharmony_ci self.bind(OVS_VPORT_FAMILY, OvsVport.ovs_vport_msg) 166962306a36Sopenharmony_ci self.upcall_packet = packet 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci def info(self, vport_name, dpifindex=0, portno=None): 167262306a36Sopenharmony_ci msg = OvsVport.ovs_vport_msg() 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci msg["cmd"] = OVS_VPORT_CMD_GET 167562306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 167662306a36Sopenharmony_ci msg["reserved"] = 0 167762306a36Sopenharmony_ci msg["dpifindex"] = dpifindex 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci if portno is None: 168062306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_name]) 168162306a36Sopenharmony_ci else: 168262306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_PORT_NO", portno]) 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_ci try: 168562306a36Sopenharmony_ci reply = self.nlm_request( 168662306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST 168762306a36Sopenharmony_ci ) 168862306a36Sopenharmony_ci reply = reply[0] 168962306a36Sopenharmony_ci except NetlinkError as ne: 169062306a36Sopenharmony_ci if ne.code == errno.ENODEV: 169162306a36Sopenharmony_ci reply = None 169262306a36Sopenharmony_ci else: 169362306a36Sopenharmony_ci raise ne 169462306a36Sopenharmony_ci return reply 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci def attach(self, dpindex, vport_ifname, ptype): 169762306a36Sopenharmony_ci msg = OvsVport.ovs_vport_msg() 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci msg["cmd"] = OVS_VPORT_CMD_NEW 170062306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 170162306a36Sopenharmony_ci msg["reserved"] = 0 170262306a36Sopenharmony_ci msg["dpifindex"] = dpindex 170362306a36Sopenharmony_ci port_type = OvsVport.str_to_type(ptype) 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type]) 170662306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 170762306a36Sopenharmony_ci msg["attrs"].append( 170862306a36Sopenharmony_ci ["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]] 170962306a36Sopenharmony_ci ) 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci try: 171262306a36Sopenharmony_ci reply = self.nlm_request( 171362306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 171462306a36Sopenharmony_ci ) 171562306a36Sopenharmony_ci reply = reply[0] 171662306a36Sopenharmony_ci except NetlinkError as ne: 171762306a36Sopenharmony_ci if ne.code == errno.EEXIST: 171862306a36Sopenharmony_ci reply = None 171962306a36Sopenharmony_ci else: 172062306a36Sopenharmony_ci raise ne 172162306a36Sopenharmony_ci return reply 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci def reset_upcall(self, dpindex, vport_ifname, p=None): 172462306a36Sopenharmony_ci msg = OvsVport.ovs_vport_msg() 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci msg["cmd"] = OVS_VPORT_CMD_SET 172762306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 172862306a36Sopenharmony_ci msg["reserved"] = 0 172962306a36Sopenharmony_ci msg["dpifindex"] = dpindex 173062306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci if p == None: 173362306a36Sopenharmony_ci p = self.upcall_packet 173462306a36Sopenharmony_ci else: 173562306a36Sopenharmony_ci self.upcall_packet = p 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [p.epid]]) 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci try: 174062306a36Sopenharmony_ci reply = self.nlm_request( 174162306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 174262306a36Sopenharmony_ci ) 174362306a36Sopenharmony_ci reply = reply[0] 174462306a36Sopenharmony_ci except NetlinkError as ne: 174562306a36Sopenharmony_ci raise ne 174662306a36Sopenharmony_ci return reply 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci def detach(self, dpindex, vport_ifname): 174962306a36Sopenharmony_ci msg = OvsVport.ovs_vport_msg() 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci msg["cmd"] = OVS_VPORT_CMD_DEL 175262306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 175362306a36Sopenharmony_ci msg["reserved"] = 0 175462306a36Sopenharmony_ci msg["dpifindex"] = dpindex 175562306a36Sopenharmony_ci msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci try: 175862306a36Sopenharmony_ci reply = self.nlm_request( 175962306a36Sopenharmony_ci msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 176062306a36Sopenharmony_ci ) 176162306a36Sopenharmony_ci reply = reply[0] 176262306a36Sopenharmony_ci except NetlinkError as ne: 176362306a36Sopenharmony_ci if ne.code == errno.ENODEV: 176462306a36Sopenharmony_ci reply = None 176562306a36Sopenharmony_ci else: 176662306a36Sopenharmony_ci raise ne 176762306a36Sopenharmony_ci return reply 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci def upcall_handler(self, handler=None): 177062306a36Sopenharmony_ci self.upcall_packet.upcall_handler(handler) 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ciclass OvsFlow(GenericNetlinkSocket): 177462306a36Sopenharmony_ci class ovs_flow_msg(ovs_dp_msg): 177562306a36Sopenharmony_ci nla_map = ( 177662306a36Sopenharmony_ci ("OVS_FLOW_ATTR_UNSPEC", "none"), 177762306a36Sopenharmony_ci ("OVS_FLOW_ATTR_KEY", "ovskey"), 177862306a36Sopenharmony_ci ("OVS_FLOW_ATTR_ACTIONS", "ovsactions"), 177962306a36Sopenharmony_ci ("OVS_FLOW_ATTR_STATS", "flowstats"), 178062306a36Sopenharmony_ci ("OVS_FLOW_ATTR_TCP_FLAGS", "uint8"), 178162306a36Sopenharmony_ci ("OVS_FLOW_ATTR_USED", "uint64"), 178262306a36Sopenharmony_ci ("OVS_FLOW_ATTR_CLEAR", "none"), 178362306a36Sopenharmony_ci ("OVS_FLOW_ATTR_MASK", "ovskey"), 178462306a36Sopenharmony_ci ("OVS_FLOW_ATTR_PROBE", "none"), 178562306a36Sopenharmony_ci ("OVS_FLOW_ATTR_UFID", "array(uint32)"), 178662306a36Sopenharmony_ci ("OVS_FLOW_ATTR_UFID_FLAGS", "uint32"), 178762306a36Sopenharmony_ci ) 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci class flowstats(nla): 179062306a36Sopenharmony_ci fields = ( 179162306a36Sopenharmony_ci ("packets", "=Q"), 179262306a36Sopenharmony_ci ("bytes", "=Q"), 179362306a36Sopenharmony_ci ) 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci def dpstr(self, more=False): 179662306a36Sopenharmony_ci ufid = self.get_attr("OVS_FLOW_ATTR_UFID") 179762306a36Sopenharmony_ci ufid_str = "" 179862306a36Sopenharmony_ci if ufid is not None: 179962306a36Sopenharmony_ci ufid_str = ( 180062306a36Sopenharmony_ci "ufid:{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}".format( 180162306a36Sopenharmony_ci ufid[0], 180262306a36Sopenharmony_ci ufid[1] >> 16, 180362306a36Sopenharmony_ci ufid[1] & 0xFFFF, 180462306a36Sopenharmony_ci ufid[2] >> 16, 180562306a36Sopenharmony_ci ufid[2] & 0, 180662306a36Sopenharmony_ci ufid[3], 180762306a36Sopenharmony_ci ) 180862306a36Sopenharmony_ci ) 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci key_field = self.get_attr("OVS_FLOW_ATTR_KEY") 181162306a36Sopenharmony_ci keymsg = None 181262306a36Sopenharmony_ci if key_field is not None: 181362306a36Sopenharmony_ci keymsg = key_field 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci mask_field = self.get_attr("OVS_FLOW_ATTR_MASK") 181662306a36Sopenharmony_ci maskmsg = None 181762306a36Sopenharmony_ci if mask_field is not None: 181862306a36Sopenharmony_ci maskmsg = mask_field 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci acts_field = self.get_attr("OVS_FLOW_ATTR_ACTIONS") 182162306a36Sopenharmony_ci actsmsg = None 182262306a36Sopenharmony_ci if acts_field is not None: 182362306a36Sopenharmony_ci actsmsg = acts_field 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci print_str = "" 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci if more: 182862306a36Sopenharmony_ci print_str += ufid_str + "," 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci if keymsg is not None: 183162306a36Sopenharmony_ci print_str += keymsg.dpstr(maskmsg, more) 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci stats = self.get_attr("OVS_FLOW_ATTR_STATS") 183462306a36Sopenharmony_ci if stats is None: 183562306a36Sopenharmony_ci print_str += " packets:0, bytes:0," 183662306a36Sopenharmony_ci else: 183762306a36Sopenharmony_ci print_str += " packets:%d, bytes:%d," % ( 183862306a36Sopenharmony_ci stats["packets"], 183962306a36Sopenharmony_ci stats["bytes"], 184062306a36Sopenharmony_ci ) 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci used = self.get_attr("OVS_FLOW_ATTR_USED") 184362306a36Sopenharmony_ci print_str += " used:" 184462306a36Sopenharmony_ci if used is None: 184562306a36Sopenharmony_ci print_str += "never," 184662306a36Sopenharmony_ci else: 184762306a36Sopenharmony_ci used_time = int(used) 184862306a36Sopenharmony_ci cur_time_sec = time.clock_gettime(time.CLOCK_MONOTONIC) 184962306a36Sopenharmony_ci used_time = (cur_time_sec * 1000) - used_time 185062306a36Sopenharmony_ci print_str += "{}s,".format(used_time / 1000) 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci print_str += " actions:" 185362306a36Sopenharmony_ci if ( 185462306a36Sopenharmony_ci actsmsg is None 185562306a36Sopenharmony_ci or "attrs" not in actsmsg 185662306a36Sopenharmony_ci or len(actsmsg["attrs"]) == 0 185762306a36Sopenharmony_ci ): 185862306a36Sopenharmony_ci print_str += "drop" 185962306a36Sopenharmony_ci else: 186062306a36Sopenharmony_ci print_str += actsmsg.dpstr(more) 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci return print_str 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci def parse(self, flowstr, actstr, dpidx=0): 186562306a36Sopenharmony_ci OVS_UFID_F_OMIT_KEY = 1 << 0 186662306a36Sopenharmony_ci OVS_UFID_F_OMIT_MASK = 1 << 1 186762306a36Sopenharmony_ci OVS_UFID_F_OMIT_ACTIONS = 1 << 2 186862306a36Sopenharmony_ci 186962306a36Sopenharmony_ci self["cmd"] = 0 187062306a36Sopenharmony_ci self["version"] = 0 187162306a36Sopenharmony_ci self["reserved"] = 0 187262306a36Sopenharmony_ci self["dpifindex"] = 0 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci if flowstr.startswith("ufid:"): 187562306a36Sopenharmony_ci count = 5 187662306a36Sopenharmony_ci while flowstr[count] != ",": 187762306a36Sopenharmony_ci count += 1 187862306a36Sopenharmony_ci ufidstr = flowstr[5:count] 187962306a36Sopenharmony_ci flowstr = flowstr[count + 1 :] 188062306a36Sopenharmony_ci else: 188162306a36Sopenharmony_ci ufidstr = str(uuid.uuid4()) 188262306a36Sopenharmony_ci uuidRawObj = uuid.UUID(ufidstr).fields 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_ci self["attrs"].append( 188562306a36Sopenharmony_ci [ 188662306a36Sopenharmony_ci "OVS_FLOW_ATTR_UFID", 188762306a36Sopenharmony_ci [ 188862306a36Sopenharmony_ci uuidRawObj[0], 188962306a36Sopenharmony_ci uuidRawObj[1] << 16 | uuidRawObj[2], 189062306a36Sopenharmony_ci uuidRawObj[3] << 24 189162306a36Sopenharmony_ci | uuidRawObj[4] << 16 189262306a36Sopenharmony_ci | uuidRawObj[5] & (0xFF << 32) >> 32, 189362306a36Sopenharmony_ci uuidRawObj[5] & (0xFFFFFFFF), 189462306a36Sopenharmony_ci ], 189562306a36Sopenharmony_ci ] 189662306a36Sopenharmony_ci ) 189762306a36Sopenharmony_ci self["attrs"].append( 189862306a36Sopenharmony_ci [ 189962306a36Sopenharmony_ci "OVS_FLOW_ATTR_UFID_FLAGS", 190062306a36Sopenharmony_ci int( 190162306a36Sopenharmony_ci OVS_UFID_F_OMIT_KEY 190262306a36Sopenharmony_ci | OVS_UFID_F_OMIT_MASK 190362306a36Sopenharmony_ci | OVS_UFID_F_OMIT_ACTIONS 190462306a36Sopenharmony_ci ), 190562306a36Sopenharmony_ci ] 190662306a36Sopenharmony_ci ) 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci k = ovskey() 190962306a36Sopenharmony_ci m = ovskey() 191062306a36Sopenharmony_ci k.parse(flowstr, m) 191162306a36Sopenharmony_ci self["attrs"].append(["OVS_FLOW_ATTR_KEY", k]) 191262306a36Sopenharmony_ci self["attrs"].append(["OVS_FLOW_ATTR_MASK", m]) 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci a = ovsactions() 191562306a36Sopenharmony_ci a.parse(actstr) 191662306a36Sopenharmony_ci self["attrs"].append(["OVS_FLOW_ATTR_ACTIONS", a]) 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci def __init__(self): 191962306a36Sopenharmony_ci GenericNetlinkSocket.__init__(self) 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci self.bind(OVS_FLOW_FAMILY, OvsFlow.ovs_flow_msg) 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci def add_flow(self, dpifindex, flowmsg): 192462306a36Sopenharmony_ci """ 192562306a36Sopenharmony_ci Send a new flow message to the kernel. 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci dpifindex should be a valid datapath obtained by calling 192862306a36Sopenharmony_ci into the OvsDatapath lookup 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci flowmsg is a flow object obtained by calling a dpparse 193162306a36Sopenharmony_ci """ 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci flowmsg["cmd"] = OVS_FLOW_CMD_NEW 193462306a36Sopenharmony_ci flowmsg["version"] = OVS_DATAPATH_VERSION 193562306a36Sopenharmony_ci flowmsg["reserved"] = 0 193662306a36Sopenharmony_ci flowmsg["dpifindex"] = dpifindex 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci try: 193962306a36Sopenharmony_ci reply = self.nlm_request( 194062306a36Sopenharmony_ci flowmsg, 194162306a36Sopenharmony_ci msg_type=self.prid, 194262306a36Sopenharmony_ci msg_flags=NLM_F_REQUEST | NLM_F_ACK, 194362306a36Sopenharmony_ci ) 194462306a36Sopenharmony_ci reply = reply[0] 194562306a36Sopenharmony_ci except NetlinkError as ne: 194662306a36Sopenharmony_ci print(flowmsg) 194762306a36Sopenharmony_ci raise ne 194862306a36Sopenharmony_ci return reply 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci def del_flows(self, dpifindex): 195162306a36Sopenharmony_ci """ 195262306a36Sopenharmony_ci Send a del message to the kernel that will drop all flows. 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_ci dpifindex should be a valid datapath obtained by calling 195562306a36Sopenharmony_ci into the OvsDatapath lookup 195662306a36Sopenharmony_ci """ 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci flowmsg = OvsFlow.ovs_flow_msg() 195962306a36Sopenharmony_ci flowmsg["cmd"] = OVS_FLOW_CMD_DEL 196062306a36Sopenharmony_ci flowmsg["version"] = OVS_DATAPATH_VERSION 196162306a36Sopenharmony_ci flowmsg["reserved"] = 0 196262306a36Sopenharmony_ci flowmsg["dpifindex"] = dpifindex 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci try: 196562306a36Sopenharmony_ci reply = self.nlm_request( 196662306a36Sopenharmony_ci flowmsg, 196762306a36Sopenharmony_ci msg_type=self.prid, 196862306a36Sopenharmony_ci msg_flags=NLM_F_REQUEST | NLM_F_ACK, 196962306a36Sopenharmony_ci ) 197062306a36Sopenharmony_ci reply = reply[0] 197162306a36Sopenharmony_ci except NetlinkError as ne: 197262306a36Sopenharmony_ci print(flowmsg) 197362306a36Sopenharmony_ci raise ne 197462306a36Sopenharmony_ci return reply 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci def dump(self, dpifindex, flowspec=None): 197762306a36Sopenharmony_ci """ 197862306a36Sopenharmony_ci Returns a list of messages containing flows. 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci dpifindex should be a valid datapath obtained by calling 198162306a36Sopenharmony_ci into the OvsDatapath lookup 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci flowpsec is a string which represents a flow in the dpctl 198462306a36Sopenharmony_ci format. 198562306a36Sopenharmony_ci """ 198662306a36Sopenharmony_ci msg = OvsFlow.ovs_flow_msg() 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci msg["cmd"] = OVS_FLOW_CMD_GET 198962306a36Sopenharmony_ci msg["version"] = OVS_DATAPATH_VERSION 199062306a36Sopenharmony_ci msg["reserved"] = 0 199162306a36Sopenharmony_ci msg["dpifindex"] = dpifindex 199262306a36Sopenharmony_ci 199362306a36Sopenharmony_ci msg_flags = NLM_F_REQUEST | NLM_F_ACK 199462306a36Sopenharmony_ci if flowspec is None: 199562306a36Sopenharmony_ci msg_flags |= NLM_F_DUMP 199662306a36Sopenharmony_ci rep = None 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci try: 199962306a36Sopenharmony_ci rep = self.nlm_request( 200062306a36Sopenharmony_ci msg, 200162306a36Sopenharmony_ci msg_type=self.prid, 200262306a36Sopenharmony_ci msg_flags=msg_flags, 200362306a36Sopenharmony_ci ) 200462306a36Sopenharmony_ci except NetlinkError as ne: 200562306a36Sopenharmony_ci raise ne 200662306a36Sopenharmony_ci return rep 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci def miss(self, packetmsg): 200962306a36Sopenharmony_ci seq = packetmsg["header"]["sequence_number"] 201062306a36Sopenharmony_ci keystr = "(none)" 201162306a36Sopenharmony_ci key_field = packetmsg.get_attr("OVS_PACKET_ATTR_KEY") 201262306a36Sopenharmony_ci if key_field is not None: 201362306a36Sopenharmony_ci keystr = key_field.dpstr(None, True) 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci pktdata = packetmsg.get_attr("OVS_PACKET_ATTR_PACKET") 201662306a36Sopenharmony_ci pktpres = "yes" if pktdata is not None else "no" 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci print("MISS upcall[%d/%s]: %s" % (seq, pktpres, keystr), flush=True) 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci def execute(self, packetmsg): 202162306a36Sopenharmony_ci print("userspace execute command") 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci def action(self, packetmsg): 202462306a36Sopenharmony_ci print("userspace action command") 202562306a36Sopenharmony_ci 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_cidef print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): 202862306a36Sopenharmony_ci dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME") 202962306a36Sopenharmony_ci base_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_STATS") 203062306a36Sopenharmony_ci megaflow_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_MEGAFLOW_STATS") 203162306a36Sopenharmony_ci user_features = dp_lookup_rep.get_attr("OVS_DP_ATTR_USER_FEATURES") 203262306a36Sopenharmony_ci masks_cache_size = dp_lookup_rep.get_attr("OVS_DP_ATTR_MASKS_CACHE_SIZE") 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci print("%s:" % dp_name) 203562306a36Sopenharmony_ci print( 203662306a36Sopenharmony_ci " lookups: hit:%d missed:%d lost:%d" 203762306a36Sopenharmony_ci % (base_stats["hit"], base_stats["missed"], base_stats["lost"]) 203862306a36Sopenharmony_ci ) 203962306a36Sopenharmony_ci print(" flows:%d" % base_stats["flows"]) 204062306a36Sopenharmony_ci pkts = base_stats["hit"] + base_stats["missed"] 204162306a36Sopenharmony_ci avg = (megaflow_stats["mask_hit"] / pkts) if pkts != 0 else 0.0 204262306a36Sopenharmony_ci print( 204362306a36Sopenharmony_ci " masks: hit:%d total:%d hit/pkt:%f" 204462306a36Sopenharmony_ci % (megaflow_stats["mask_hit"], megaflow_stats["masks"], avg) 204562306a36Sopenharmony_ci ) 204662306a36Sopenharmony_ci print(" caches:") 204762306a36Sopenharmony_ci print(" masks-cache: size:%d" % masks_cache_size) 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci if user_features is not None: 205062306a36Sopenharmony_ci print(" features: 0x%X" % user_features) 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci # port print out 205362306a36Sopenharmony_ci for iface in ndb.interfaces: 205462306a36Sopenharmony_ci rep = vpl.info(iface.ifname, ifindex) 205562306a36Sopenharmony_ci if rep is not None: 205662306a36Sopenharmony_ci print( 205762306a36Sopenharmony_ci " port %d: %s (%s)" 205862306a36Sopenharmony_ci % ( 205962306a36Sopenharmony_ci rep.get_attr("OVS_VPORT_ATTR_PORT_NO"), 206062306a36Sopenharmony_ci rep.get_attr("OVS_VPORT_ATTR_NAME"), 206162306a36Sopenharmony_ci OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")), 206262306a36Sopenharmony_ci ) 206362306a36Sopenharmony_ci ) 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_cidef main(argv): 206762306a36Sopenharmony_ci nlmsg_atoms.ovskey = ovskey 206862306a36Sopenharmony_ci nlmsg_atoms.ovsactions = ovsactions 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci # version check for pyroute2 207162306a36Sopenharmony_ci prverscheck = pyroute2.__version__.split(".") 207262306a36Sopenharmony_ci if int(prverscheck[0]) == 0 and int(prverscheck[1]) < 6: 207362306a36Sopenharmony_ci print("Need to upgrade the python pyroute2 package to >= 0.6.") 207462306a36Sopenharmony_ci sys.exit(0) 207562306a36Sopenharmony_ci 207662306a36Sopenharmony_ci parser = argparse.ArgumentParser() 207762306a36Sopenharmony_ci parser.add_argument( 207862306a36Sopenharmony_ci "-v", 207962306a36Sopenharmony_ci "--verbose", 208062306a36Sopenharmony_ci action="count", 208162306a36Sopenharmony_ci help="Increment 'verbose' output counter.", 208262306a36Sopenharmony_ci default=0, 208362306a36Sopenharmony_ci ) 208462306a36Sopenharmony_ci subparsers = parser.add_subparsers() 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_ci showdpcmd = subparsers.add_parser("show") 208762306a36Sopenharmony_ci showdpcmd.add_argument( 208862306a36Sopenharmony_ci "showdp", metavar="N", type=str, nargs="?", help="Datapath Name" 208962306a36Sopenharmony_ci ) 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ci adddpcmd = subparsers.add_parser("add-dp") 209262306a36Sopenharmony_ci adddpcmd.add_argument("adddp", help="Datapath Name") 209362306a36Sopenharmony_ci adddpcmd.add_argument( 209462306a36Sopenharmony_ci "-u", 209562306a36Sopenharmony_ci "--upcall", 209662306a36Sopenharmony_ci action="store_true", 209762306a36Sopenharmony_ci help="Leave open a reader for upcalls", 209862306a36Sopenharmony_ci ) 209962306a36Sopenharmony_ci adddpcmd.add_argument( 210062306a36Sopenharmony_ci "-V", 210162306a36Sopenharmony_ci "--versioning", 210262306a36Sopenharmony_ci required=False, 210362306a36Sopenharmony_ci help="Specify a custom version / feature string", 210462306a36Sopenharmony_ci ) 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci deldpcmd = subparsers.add_parser("del-dp") 210762306a36Sopenharmony_ci deldpcmd.add_argument("deldp", help="Datapath Name") 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci addifcmd = subparsers.add_parser("add-if") 211062306a36Sopenharmony_ci addifcmd.add_argument("dpname", help="Datapath Name") 211162306a36Sopenharmony_ci addifcmd.add_argument("addif", help="Interface name for adding") 211262306a36Sopenharmony_ci addifcmd.add_argument( 211362306a36Sopenharmony_ci "-u", 211462306a36Sopenharmony_ci "--upcall", 211562306a36Sopenharmony_ci action="store_true", 211662306a36Sopenharmony_ci help="Leave open a reader for upcalls", 211762306a36Sopenharmony_ci ) 211862306a36Sopenharmony_ci addifcmd.add_argument( 211962306a36Sopenharmony_ci "-t", 212062306a36Sopenharmony_ci "--ptype", 212162306a36Sopenharmony_ci type=str, 212262306a36Sopenharmony_ci default="netdev", 212362306a36Sopenharmony_ci choices=["netdev", "internal"], 212462306a36Sopenharmony_ci help="Interface type (default netdev)", 212562306a36Sopenharmony_ci ) 212662306a36Sopenharmony_ci delifcmd = subparsers.add_parser("del-if") 212762306a36Sopenharmony_ci delifcmd.add_argument("dpname", help="Datapath Name") 212862306a36Sopenharmony_ci delifcmd.add_argument("delif", help="Interface name for adding") 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci dumpflcmd = subparsers.add_parser("dump-flows") 213162306a36Sopenharmony_ci dumpflcmd.add_argument("dumpdp", help="Datapath Name") 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci addflcmd = subparsers.add_parser("add-flow") 213462306a36Sopenharmony_ci addflcmd.add_argument("flbr", help="Datapath name") 213562306a36Sopenharmony_ci addflcmd.add_argument("flow", help="Flow specification") 213662306a36Sopenharmony_ci addflcmd.add_argument("acts", help="Flow actions") 213762306a36Sopenharmony_ci 213862306a36Sopenharmony_ci delfscmd = subparsers.add_parser("del-flows") 213962306a36Sopenharmony_ci delfscmd.add_argument("flsbr", help="Datapath name") 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci args = parser.parse_args() 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci if args.verbose > 0: 214462306a36Sopenharmony_ci if args.verbose > 1: 214562306a36Sopenharmony_ci logging.basicConfig(level=logging.DEBUG) 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ci ovspk = OvsPacket() 214862306a36Sopenharmony_ci ovsdp = OvsDatapath() 214962306a36Sopenharmony_ci ovsvp = OvsVport(ovspk) 215062306a36Sopenharmony_ci ovsflow = OvsFlow() 215162306a36Sopenharmony_ci ndb = NDB() 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci sys.setrecursionlimit(100000) 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci if hasattr(args, "showdp"): 215662306a36Sopenharmony_ci found = False 215762306a36Sopenharmony_ci for iface in ndb.interfaces: 215862306a36Sopenharmony_ci rep = None 215962306a36Sopenharmony_ci if args.showdp is None: 216062306a36Sopenharmony_ci rep = ovsdp.info(iface.ifname, 0) 216162306a36Sopenharmony_ci elif args.showdp == iface.ifname: 216262306a36Sopenharmony_ci rep = ovsdp.info(iface.ifname, 0) 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci if rep is not None: 216562306a36Sopenharmony_ci found = True 216662306a36Sopenharmony_ci print_ovsdp_full(rep, iface.index, ndb, ovsvp) 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci if not found: 216962306a36Sopenharmony_ci msg = "No DP found" 217062306a36Sopenharmony_ci if args.showdp is not None: 217162306a36Sopenharmony_ci msg += ":'%s'" % args.showdp 217262306a36Sopenharmony_ci print(msg) 217362306a36Sopenharmony_ci elif hasattr(args, "adddp"): 217462306a36Sopenharmony_ci rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk) 217562306a36Sopenharmony_ci if rep is None: 217662306a36Sopenharmony_ci print("DP '%s' already exists" % args.adddp) 217762306a36Sopenharmony_ci else: 217862306a36Sopenharmony_ci print("DP '%s' added" % args.adddp) 217962306a36Sopenharmony_ci if args.upcall: 218062306a36Sopenharmony_ci ovspk.upcall_handler(ovsflow) 218162306a36Sopenharmony_ci elif hasattr(args, "deldp"): 218262306a36Sopenharmony_ci ovsdp.destroy(args.deldp) 218362306a36Sopenharmony_ci elif hasattr(args, "addif"): 218462306a36Sopenharmony_ci rep = ovsdp.info(args.dpname, 0) 218562306a36Sopenharmony_ci if rep is None: 218662306a36Sopenharmony_ci print("DP '%s' not found." % args.dpname) 218762306a36Sopenharmony_ci return 1 218862306a36Sopenharmony_ci dpindex = rep["dpifindex"] 218962306a36Sopenharmony_ci rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype) 219062306a36Sopenharmony_ci msg = "vport '%s'" % args.addif 219162306a36Sopenharmony_ci if rep and rep["header"]["error"] is None: 219262306a36Sopenharmony_ci msg += " added." 219362306a36Sopenharmony_ci else: 219462306a36Sopenharmony_ci msg += " failed to add." 219562306a36Sopenharmony_ci if args.upcall: 219662306a36Sopenharmony_ci if rep is None: 219762306a36Sopenharmony_ci rep = ovsvp.reset_upcall(dpindex, args.addif, ovspk) 219862306a36Sopenharmony_ci ovsvp.upcall_handler(ovsflow) 219962306a36Sopenharmony_ci elif hasattr(args, "delif"): 220062306a36Sopenharmony_ci rep = ovsdp.info(args.dpname, 0) 220162306a36Sopenharmony_ci if rep is None: 220262306a36Sopenharmony_ci print("DP '%s' not found." % args.dpname) 220362306a36Sopenharmony_ci return 1 220462306a36Sopenharmony_ci rep = ovsvp.detach(rep["dpifindex"], args.delif) 220562306a36Sopenharmony_ci msg = "vport '%s'" % args.delif 220662306a36Sopenharmony_ci if rep and rep["header"]["error"] is None: 220762306a36Sopenharmony_ci msg += " removed." 220862306a36Sopenharmony_ci else: 220962306a36Sopenharmony_ci msg += " failed to remove." 221062306a36Sopenharmony_ci elif hasattr(args, "dumpdp"): 221162306a36Sopenharmony_ci rep = ovsdp.info(args.dumpdp, 0) 221262306a36Sopenharmony_ci if rep is None: 221362306a36Sopenharmony_ci print("DP '%s' not found." % args.dumpdp) 221462306a36Sopenharmony_ci return 1 221562306a36Sopenharmony_ci rep = ovsflow.dump(rep["dpifindex"]) 221662306a36Sopenharmony_ci for flow in rep: 221762306a36Sopenharmony_ci print(flow.dpstr(True if args.verbose > 0 else False)) 221862306a36Sopenharmony_ci elif hasattr(args, "flbr"): 221962306a36Sopenharmony_ci rep = ovsdp.info(args.flbr, 0) 222062306a36Sopenharmony_ci if rep is None: 222162306a36Sopenharmony_ci print("DP '%s' not found." % args.flbr) 222262306a36Sopenharmony_ci return 1 222362306a36Sopenharmony_ci flow = OvsFlow.ovs_flow_msg() 222462306a36Sopenharmony_ci flow.parse(args.flow, args.acts, rep["dpifindex"]) 222562306a36Sopenharmony_ci ovsflow.add_flow(rep["dpifindex"], flow) 222662306a36Sopenharmony_ci elif hasattr(args, "flsbr"): 222762306a36Sopenharmony_ci rep = ovsdp.info(args.flsbr, 0) 222862306a36Sopenharmony_ci if rep is None: 222962306a36Sopenharmony_ci print("DP '%s' not found." % args.flsbr) 223062306a36Sopenharmony_ci ovsflow.del_flows(rep["dpifindex"]) 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci return 0 223362306a36Sopenharmony_ci 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ciif __name__ == "__main__": 223662306a36Sopenharmony_ci sys.exit(main(sys.argv)) 2237