125f16c87SAaron Conole#!/usr/bin/env python3 225f16c87SAaron Conole# SPDX-License-Identifier: GPL-2.0 325f16c87SAaron Conole 425f16c87SAaron Conole# Controls the openvswitch module. Part of the kselftest suite, but 525f16c87SAaron Conole# can be used for some diagnostic purpose as well. 625f16c87SAaron Conole 725f16c87SAaron Conoleimport argparse 825f16c87SAaron Conoleimport errno 9e52b07aaSAaron Conoleimport ipaddress 10e52b07aaSAaron Conoleimport logging 119feac87bSAaron Conoleimport multiprocessing 12918423fdSAaron Conoleimport re 139feac87bSAaron Conoleimport struct 1425f16c87SAaron Conoleimport sys 15e52b07aaSAaron Conoleimport time 16918423fdSAaron Conoleimport types 17918423fdSAaron Conoleimport uuid 1825f16c87SAaron Conole 1925f16c87SAaron Conoletry: 2025f16c87SAaron Conole from pyroute2 import NDB 2125f16c87SAaron Conole 22e52b07aaSAaron Conole from pyroute2.netlink import NLA_F_NESTED 2325f16c87SAaron Conole from pyroute2.netlink import NLM_F_ACK 24e52b07aaSAaron Conole from pyroute2.netlink import NLM_F_DUMP 2525f16c87SAaron Conole from pyroute2.netlink import NLM_F_REQUEST 2625f16c87SAaron Conole from pyroute2.netlink import genlmsg 2725f16c87SAaron Conole from pyroute2.netlink import nla 28e52b07aaSAaron Conole from pyroute2.netlink import nlmsg_atoms 2925f16c87SAaron Conole from pyroute2.netlink.exceptions import NetlinkError 3025f16c87SAaron Conole from pyroute2.netlink.generic import GenericNetlinkSocket 3192e37f20SAaron Conole import pyroute2 3292e37f20SAaron Conole 3325f16c87SAaron Conoleexcept ModuleNotFoundError: 3492e37f20SAaron Conole print("Need to install the python pyroute2 package >= 0.6.") 3525f16c87SAaron Conole sys.exit(0) 3625f16c87SAaron Conole 3725f16c87SAaron Conole 3825f16c87SAaron ConoleOVS_DATAPATH_FAMILY = "ovs_datapath" 3925f16c87SAaron ConoleOVS_VPORT_FAMILY = "ovs_vport" 4025f16c87SAaron ConoleOVS_FLOW_FAMILY = "ovs_flow" 4125f16c87SAaron ConoleOVS_PACKET_FAMILY = "ovs_packet" 4225f16c87SAaron ConoleOVS_METER_FAMILY = "ovs_meter" 4325f16c87SAaron ConoleOVS_CT_LIMIT_FAMILY = "ovs_ct_limit" 4425f16c87SAaron Conole 4525f16c87SAaron ConoleOVS_DATAPATH_VERSION = 2 4625f16c87SAaron ConoleOVS_DP_CMD_NEW = 1 4725f16c87SAaron ConoleOVS_DP_CMD_DEL = 2 4825f16c87SAaron ConoleOVS_DP_CMD_GET = 3 4925f16c87SAaron ConoleOVS_DP_CMD_SET = 4 5025f16c87SAaron Conole 5125f16c87SAaron ConoleOVS_VPORT_CMD_NEW = 1 5225f16c87SAaron ConoleOVS_VPORT_CMD_DEL = 2 5325f16c87SAaron ConoleOVS_VPORT_CMD_GET = 3 5425f16c87SAaron ConoleOVS_VPORT_CMD_SET = 4 5525f16c87SAaron Conole 56e52b07aaSAaron ConoleOVS_FLOW_CMD_NEW = 1 57e52b07aaSAaron ConoleOVS_FLOW_CMD_DEL = 2 58e52b07aaSAaron ConoleOVS_FLOW_CMD_GET = 3 59e52b07aaSAaron ConoleOVS_FLOW_CMD_SET = 4 60e52b07aaSAaron Conole 61e52b07aaSAaron Conole 62e52b07aaSAaron Conoledef macstr(mac): 63e52b07aaSAaron Conole outstr = ":".join(["%02X" % i for i in mac]) 64e52b07aaSAaron Conole return outstr 65e52b07aaSAaron Conole 66e52b07aaSAaron Conole 672893ba9cSAaron Conoledef strcspn(str1, str2): 682893ba9cSAaron Conole tot = 0 692893ba9cSAaron Conole for char in str1: 702893ba9cSAaron Conole if str2.find(char) != -1: 712893ba9cSAaron Conole return tot 722893ba9cSAaron Conole tot += 1 732893ba9cSAaron Conole return tot 742893ba9cSAaron Conole 752893ba9cSAaron Conole 76918423fdSAaron Conoledef strspn(str1, str2): 77918423fdSAaron Conole tot = 0 78918423fdSAaron Conole for char in str1: 79918423fdSAaron Conole if str2.find(char) == -1: 80918423fdSAaron Conole return tot 81918423fdSAaron Conole tot += 1 82918423fdSAaron Conole return tot 83918423fdSAaron Conole 84918423fdSAaron Conole 85918423fdSAaron Conoledef intparse(statestr, defmask="0xffffffff"): 86918423fdSAaron Conole totalparse = strspn(statestr, "0123456789abcdefABCDEFx/") 87918423fdSAaron Conole # scan until "/" 88918423fdSAaron Conole count = strspn(statestr, "x0123456789abcdefABCDEF") 89918423fdSAaron Conole 90918423fdSAaron Conole firstnum = statestr[:count] 91918423fdSAaron Conole if firstnum[-1] == "/": 92918423fdSAaron Conole firstnum = firstnum[:-1] 93918423fdSAaron Conole k = int(firstnum, 0) 94918423fdSAaron Conole 95918423fdSAaron Conole m = None 96918423fdSAaron Conole if defmask is not None: 97918423fdSAaron Conole secondnum = defmask 98918423fdSAaron Conole if statestr[count] == "/": 99918423fdSAaron Conole secondnum = statestr[count + 1 :] # this is wrong... 100918423fdSAaron Conole m = int(secondnum, 0) 101918423fdSAaron Conole 102918423fdSAaron Conole return statestr[totalparse + 1 :], k, m 103918423fdSAaron Conole 104918423fdSAaron Conole 105918423fdSAaron Conoledef parse_flags(flag_str, flag_vals): 106918423fdSAaron Conole bitResult = 0 107918423fdSAaron Conole maskResult = 0 108918423fdSAaron Conole 109918423fdSAaron Conole if len(flag_str) == 0: 110918423fdSAaron Conole return flag_str, bitResult, maskResult 111918423fdSAaron Conole 112918423fdSAaron Conole if flag_str[0].isdigit(): 113918423fdSAaron Conole idx = 0 114918423fdSAaron Conole while flag_str[idx].isdigit() or flag_str[idx] == "x": 115918423fdSAaron Conole idx += 1 116918423fdSAaron Conole digits = flag_str[:idx] 117918423fdSAaron Conole flag_str = flag_str[idx:] 118918423fdSAaron Conole 119918423fdSAaron Conole bitResult = int(digits, 0) 120918423fdSAaron Conole maskResult = int(digits, 0) 121918423fdSAaron Conole 122918423fdSAaron Conole while len(flag_str) > 0 and (flag_str[0] == "+" or flag_str[0] == "-"): 123918423fdSAaron Conole if flag_str[0] == "+": 124918423fdSAaron Conole setFlag = True 125918423fdSAaron Conole elif flag_str[0] == "-": 126918423fdSAaron Conole setFlag = False 127918423fdSAaron Conole 128918423fdSAaron Conole flag_str = flag_str[1:] 129918423fdSAaron Conole 130918423fdSAaron Conole flag_len = 0 131918423fdSAaron Conole while ( 132918423fdSAaron Conole flag_str[flag_len] != "+" 133918423fdSAaron Conole and flag_str[flag_len] != "-" 134918423fdSAaron Conole and flag_str[flag_len] != "," 135918423fdSAaron Conole and flag_str[flag_len] != ")" 136918423fdSAaron Conole ): 137918423fdSAaron Conole flag_len += 1 138918423fdSAaron Conole 139918423fdSAaron Conole flag = flag_str[0:flag_len] 140918423fdSAaron Conole 141918423fdSAaron Conole if flag in flag_vals: 142918423fdSAaron Conole if maskResult & flag_vals[flag]: 143918423fdSAaron Conole raise KeyError( 144918423fdSAaron Conole "Flag %s set once, cannot be set in multiples" % flag 145918423fdSAaron Conole ) 146918423fdSAaron Conole 147918423fdSAaron Conole if setFlag: 148918423fdSAaron Conole bitResult |= flag_vals[flag] 149918423fdSAaron Conole 150918423fdSAaron Conole maskResult |= flag_vals[flag] 151918423fdSAaron Conole else: 152918423fdSAaron Conole raise KeyError("Missing flag value: %s" % flag) 153918423fdSAaron Conole 154918423fdSAaron Conole flag_str = flag_str[flag_len:] 155918423fdSAaron Conole 156918423fdSAaron Conole return flag_str, bitResult, maskResult 157918423fdSAaron Conole 158918423fdSAaron Conole 159918423fdSAaron Conoledef parse_ct_state(statestr): 160918423fdSAaron Conole ct_flags = { 161918423fdSAaron Conole "new": 1 << 0, 162918423fdSAaron Conole "est": 1 << 1, 163918423fdSAaron Conole "rel": 1 << 2, 164918423fdSAaron Conole "rpl": 1 << 3, 165918423fdSAaron Conole "inv": 1 << 4, 166918423fdSAaron Conole "trk": 1 << 5, 167918423fdSAaron Conole "snat": 1 << 6, 168918423fdSAaron Conole "dnat": 1 << 7, 169918423fdSAaron Conole } 170918423fdSAaron Conole 171918423fdSAaron Conole return parse_flags(statestr, ct_flags) 172918423fdSAaron Conole 173918423fdSAaron Conole 1749f1179fbSAdrian Morenodef convert_mac(data): 1759f1179fbSAdrian Moreno def to_bytes(mac): 1769f1179fbSAdrian Moreno mac_split = mac.split(":") 177e52b07aaSAaron Conole ret = bytearray([int(i, 16) for i in mac_split]) 178e52b07aaSAaron Conole return bytes(ret) 179e52b07aaSAaron Conole 1809f1179fbSAdrian Moreno mac_str, _, mask_str = data.partition('/') 181e52b07aaSAaron Conole 1829f1179fbSAdrian Moreno if not mac_str: 1839f1179fbSAdrian Moreno mac_str = mask_str = "00:00:00:00:00:00" 1849f1179fbSAdrian Moreno elif not mask_str: 1859f1179fbSAdrian Moreno mask_str = "FF:FF:FF:FF:FF:FF" 186e52b07aaSAaron Conole 1879f1179fbSAdrian Moreno return to_bytes(mac_str), to_bytes(mask_str) 188e52b07aaSAaron Conole 1899f1179fbSAdrian Morenodef convert_ipv4(data): 1909f1179fbSAdrian Moreno ip, _, mask = data.partition('/') 1919f1179fbSAdrian Moreno 1929f1179fbSAdrian Moreno if not ip: 1939f1179fbSAdrian Moreno ip = mask = 0 1949f1179fbSAdrian Moreno elif not mask: 1959f1179fbSAdrian Moreno mask = 0xFFFFFFFF 1969f1179fbSAdrian Moreno elif mask.isdigit(): 1979f1179fbSAdrian Moreno mask = (0xFFFFFFFF << (32 - int(mask))) & 0xFFFFFFFF 1989f1179fbSAdrian Moreno 1999f1179fbSAdrian Moreno return int(ipaddress.IPv4Address(ip)), int(ipaddress.IPv4Address(mask)) 2009f1179fbSAdrian Moreno 2019f1179fbSAdrian Morenodef convert_int(size): 2029f1179fbSAdrian Moreno def convert_int_sized(data): 2039f1179fbSAdrian Moreno value, _, mask = data.partition('/') 2049f1179fbSAdrian Moreno 2059f1179fbSAdrian Moreno if not value: 2069f1179fbSAdrian Moreno return 0, 0 2079f1179fbSAdrian Moreno elif not mask: 2089f1179fbSAdrian Moreno return int(value, 0), pow(2, size) - 1 2099f1179fbSAdrian Moreno else: 2109f1179fbSAdrian Moreno return int(value, 0), int(mask, 0) 2119f1179fbSAdrian Moreno 2129f1179fbSAdrian Moreno return convert_int_sized 21325f16c87SAaron Conole 214918423fdSAaron Conoledef parse_starts_block(block_str, scanstr, returnskipped, scanregex=False): 215918423fdSAaron Conole if scanregex: 216918423fdSAaron Conole m = re.search(scanstr, block_str) 217918423fdSAaron Conole if m is None: 218918423fdSAaron Conole if returnskipped: 219918423fdSAaron Conole return block_str 220918423fdSAaron Conole return False 221918423fdSAaron Conole if returnskipped: 222918423fdSAaron Conole block_str = block_str[len(m.group(0)) :] 223918423fdSAaron Conole return block_str 224918423fdSAaron Conole return True 225918423fdSAaron Conole 226918423fdSAaron Conole if block_str.startswith(scanstr): 227918423fdSAaron Conole if returnskipped: 228918423fdSAaron Conole block_str = block_str[len(scanstr) :] 229918423fdSAaron Conole else: 230918423fdSAaron Conole return True 231918423fdSAaron Conole 232918423fdSAaron Conole if returnskipped: 233918423fdSAaron Conole return block_str 234918423fdSAaron Conole 235918423fdSAaron Conole return False 236918423fdSAaron Conole 237918423fdSAaron Conole 238918423fdSAaron Conoledef parse_extract_field( 239918423fdSAaron Conole block_str, fieldstr, scanfmt, convert, masked=False, defval=None 240918423fdSAaron Conole): 241918423fdSAaron Conole if fieldstr and not block_str.startswith(fieldstr): 242918423fdSAaron Conole return block_str, defval 243918423fdSAaron Conole 244918423fdSAaron Conole if fieldstr: 245918423fdSAaron Conole str_skiplen = len(fieldstr) 246918423fdSAaron Conole str_skipped = block_str[str_skiplen:] 247918423fdSAaron Conole if str_skiplen == 0: 248918423fdSAaron Conole return str_skipped, defval 249918423fdSAaron Conole else: 250918423fdSAaron Conole str_skiplen = 0 251918423fdSAaron Conole str_skipped = block_str 252918423fdSAaron Conole 253918423fdSAaron Conole m = re.search(scanfmt, str_skipped) 254918423fdSAaron Conole if m is None: 255918423fdSAaron Conole raise ValueError("Bad fmt string") 256918423fdSAaron Conole 257918423fdSAaron Conole data = m.group(0) 258918423fdSAaron Conole if convert: 259918423fdSAaron Conole data = convert(m.group(0)) 260918423fdSAaron Conole 261918423fdSAaron Conole str_skipped = str_skipped[len(m.group(0)) :] 262918423fdSAaron Conole if masked: 263918423fdSAaron Conole if str_skipped[0] == "/": 264918423fdSAaron Conole raise ValueError("Masking support TBD...") 265918423fdSAaron Conole 266918423fdSAaron Conole str_skipped = str_skipped[strspn(str_skipped, ", ") :] 267918423fdSAaron Conole return str_skipped, data 268918423fdSAaron Conole 269918423fdSAaron Conole 27025f16c87SAaron Conoleclass ovs_dp_msg(genlmsg): 27125f16c87SAaron Conole # include the OVS version 27225f16c87SAaron Conole # We need a custom header rather than just being able to rely on 27325f16c87SAaron Conole # genlmsg because fields ends up not expressing everything correctly 27425f16c87SAaron Conole # if we use the canonical example of setting fields = (('customfield',),) 27525f16c87SAaron Conole fields = genlmsg.fields + (("dpifindex", "I"),) 27625f16c87SAaron Conole 27725f16c87SAaron Conole 278e52b07aaSAaron Conoleclass ovsactions(nla): 279e52b07aaSAaron Conole nla_flags = NLA_F_NESTED 280e52b07aaSAaron Conole 281e52b07aaSAaron Conole nla_map = ( 282e52b07aaSAaron Conole ("OVS_ACTION_ATTR_UNSPEC", "none"), 283e52b07aaSAaron Conole ("OVS_ACTION_ATTR_OUTPUT", "uint32"), 284e52b07aaSAaron Conole ("OVS_ACTION_ATTR_USERSPACE", "userspace"), 285e52b07aaSAaron Conole ("OVS_ACTION_ATTR_SET", "none"), 286e52b07aaSAaron Conole ("OVS_ACTION_ATTR_PUSH_VLAN", "none"), 287e52b07aaSAaron Conole ("OVS_ACTION_ATTR_POP_VLAN", "flag"), 288e52b07aaSAaron Conole ("OVS_ACTION_ATTR_SAMPLE", "none"), 289e52b07aaSAaron Conole ("OVS_ACTION_ATTR_RECIRC", "uint32"), 290e52b07aaSAaron Conole ("OVS_ACTION_ATTR_HASH", "none"), 291e52b07aaSAaron Conole ("OVS_ACTION_ATTR_PUSH_MPLS", "none"), 292e52b07aaSAaron Conole ("OVS_ACTION_ATTR_POP_MPLS", "flag"), 293e52b07aaSAaron Conole ("OVS_ACTION_ATTR_SET_MASKED", "none"), 294e52b07aaSAaron Conole ("OVS_ACTION_ATTR_CT", "ctact"), 295e52b07aaSAaron Conole ("OVS_ACTION_ATTR_TRUNC", "uint32"), 296e52b07aaSAaron Conole ("OVS_ACTION_ATTR_PUSH_ETH", "none"), 297e52b07aaSAaron Conole ("OVS_ACTION_ATTR_POP_ETH", "flag"), 298e52b07aaSAaron Conole ("OVS_ACTION_ATTR_CT_CLEAR", "flag"), 299e52b07aaSAaron Conole ("OVS_ACTION_ATTR_PUSH_NSH", "none"), 300e52b07aaSAaron Conole ("OVS_ACTION_ATTR_POP_NSH", "flag"), 301e52b07aaSAaron Conole ("OVS_ACTION_ATTR_METER", "none"), 3024c3157ddSAaron Conole ("OVS_ACTION_ATTR_CLONE", "recursive"), 303e52b07aaSAaron Conole ("OVS_ACTION_ATTR_CHECK_PKT_LEN", "none"), 304e52b07aaSAaron Conole ("OVS_ACTION_ATTR_ADD_MPLS", "none"), 305e52b07aaSAaron Conole ("OVS_ACTION_ATTR_DEC_TTL", "none"), 306e7bc7db9SEric Garver ("OVS_ACTION_ATTR_DROP", "uint32"), 307e52b07aaSAaron Conole ) 308e52b07aaSAaron Conole 309e52b07aaSAaron Conole class ctact(nla): 310e52b07aaSAaron Conole nla_flags = NLA_F_NESTED 311e52b07aaSAaron Conole 312e52b07aaSAaron Conole nla_map = ( 313e52b07aaSAaron Conole ("OVS_CT_ATTR_NONE", "none"), 314e52b07aaSAaron Conole ("OVS_CT_ATTR_COMMIT", "flag"), 315e52b07aaSAaron Conole ("OVS_CT_ATTR_ZONE", "uint16"), 316e52b07aaSAaron Conole ("OVS_CT_ATTR_MARK", "none"), 317e52b07aaSAaron Conole ("OVS_CT_ATTR_LABELS", "none"), 318e52b07aaSAaron Conole ("OVS_CT_ATTR_HELPER", "asciiz"), 319e52b07aaSAaron Conole ("OVS_CT_ATTR_NAT", "natattr"), 320e52b07aaSAaron Conole ("OVS_CT_ATTR_FORCE_COMMIT", "flag"), 321e52b07aaSAaron Conole ("OVS_CT_ATTR_EVENTMASK", "uint32"), 322e52b07aaSAaron Conole ("OVS_CT_ATTR_TIMEOUT", "asciiz"), 323e52b07aaSAaron Conole ) 324e52b07aaSAaron Conole 325e52b07aaSAaron Conole class natattr(nla): 326e52b07aaSAaron Conole nla_flags = NLA_F_NESTED 327e52b07aaSAaron Conole 328e52b07aaSAaron Conole nla_map = ( 329e52b07aaSAaron Conole ("OVS_NAT_ATTR_NONE", "none"), 330e52b07aaSAaron Conole ("OVS_NAT_ATTR_SRC", "flag"), 331e52b07aaSAaron Conole ("OVS_NAT_ATTR_DST", "flag"), 332e52b07aaSAaron Conole ("OVS_NAT_ATTR_IP_MIN", "ipaddr"), 333e52b07aaSAaron Conole ("OVS_NAT_ATTR_IP_MAX", "ipaddr"), 334e52b07aaSAaron Conole ("OVS_NAT_ATTR_PROTO_MIN", "uint16"), 335e52b07aaSAaron Conole ("OVS_NAT_ATTR_PROTO_MAX", "uint16"), 336e52b07aaSAaron Conole ("OVS_NAT_ATTR_PERSISTENT", "flag"), 337e52b07aaSAaron Conole ("OVS_NAT_ATTR_PROTO_HASH", "flag"), 338e52b07aaSAaron Conole ("OVS_NAT_ATTR_PROTO_RANDOM", "flag"), 339e52b07aaSAaron Conole ) 340e52b07aaSAaron Conole 341e52b07aaSAaron Conole def dpstr(self, more=False): 342e52b07aaSAaron Conole print_str = "nat(" 343e52b07aaSAaron Conole 344e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_SRC"): 345e52b07aaSAaron Conole print_str += "src" 346e52b07aaSAaron Conole elif self.get_attr("OVS_NAT_ATTR_DST"): 347e52b07aaSAaron Conole print_str += "dst" 348e52b07aaSAaron Conole else: 349e52b07aaSAaron Conole print_str += "XXX-unknown-nat" 350e52b07aaSAaron Conole 351e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_IP_MIN") or self.get_attr( 352e52b07aaSAaron Conole "OVS_NAT_ATTR_IP_MAX" 353e52b07aaSAaron Conole ): 354e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_IP_MIN"): 355e52b07aaSAaron Conole print_str += "=%s," % str( 356e52b07aaSAaron Conole self.get_attr("OVS_NAT_ATTR_IP_MIN") 357e52b07aaSAaron Conole ) 358e52b07aaSAaron Conole 359e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_IP_MAX"): 360e52b07aaSAaron Conole print_str += "-%s," % str( 361e52b07aaSAaron Conole self.get_attr("OVS_NAT_ATTR_IP_MAX") 362e52b07aaSAaron Conole ) 363e52b07aaSAaron Conole else: 364e52b07aaSAaron Conole print_str += "," 365e52b07aaSAaron Conole 366e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_PROTO_MIN"): 367e52b07aaSAaron Conole print_str += "proto_min=%d," % self.get_attr( 368e52b07aaSAaron Conole "OVS_NAT_ATTR_PROTO_MIN" 369e52b07aaSAaron Conole ) 370e52b07aaSAaron Conole 371e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_PROTO_MAX"): 372e52b07aaSAaron Conole print_str += "proto_max=%d," % self.get_attr( 373e52b07aaSAaron Conole "OVS_NAT_ATTR_PROTO_MAX" 374e52b07aaSAaron Conole ) 375e52b07aaSAaron Conole 376e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_PERSISTENT"): 377e52b07aaSAaron Conole print_str += "persistent," 378e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_HASH"): 379e52b07aaSAaron Conole print_str += "hash," 380e52b07aaSAaron Conole if self.get_attr("OVS_NAT_ATTR_RANDOM"): 381e52b07aaSAaron Conole print_str += "random" 382e52b07aaSAaron Conole print_str += ")" 383e52b07aaSAaron Conole return print_str 384e52b07aaSAaron Conole 385e52b07aaSAaron Conole def dpstr(self, more=False): 386e52b07aaSAaron Conole print_str = "ct(" 387e52b07aaSAaron Conole 388e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_COMMIT") is not None: 389e52b07aaSAaron Conole print_str += "commit," 390e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_ZONE") is not None: 391e52b07aaSAaron Conole print_str += "zone=%d," % self.get_attr("OVS_CT_ATTR_ZONE") 392e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_HELPER") is not None: 393e52b07aaSAaron Conole print_str += "helper=%s," % self.get_attr("OVS_CT_ATTR_HELPER") 394e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_NAT") is not None: 395e52b07aaSAaron Conole print_str += self.get_attr("OVS_CT_ATTR_NAT").dpstr(more) 396e52b07aaSAaron Conole print_str += "," 397e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_FORCE_COMMIT") is not None: 398e52b07aaSAaron Conole print_str += "force," 399e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_EVENTMASK") is not None: 400e52b07aaSAaron Conole print_str += "emask=0x%X," % self.get_attr( 401e52b07aaSAaron Conole "OVS_CT_ATTR_EVENTMASK" 402e52b07aaSAaron Conole ) 403e52b07aaSAaron Conole if self.get_attr("OVS_CT_ATTR_TIMEOUT") is not None: 404e52b07aaSAaron Conole print_str += "timeout=%s" % self.get_attr( 405e52b07aaSAaron Conole "OVS_CT_ATTR_TIMEOUT" 406e52b07aaSAaron Conole ) 407e52b07aaSAaron Conole print_str += ")" 408e52b07aaSAaron Conole return print_str 409e52b07aaSAaron Conole 410e52b07aaSAaron Conole class userspace(nla): 411e52b07aaSAaron Conole nla_flags = NLA_F_NESTED 412e52b07aaSAaron Conole 413e52b07aaSAaron Conole nla_map = ( 414e52b07aaSAaron Conole ("OVS_USERSPACE_ATTR_UNUSED", "none"), 415e52b07aaSAaron Conole ("OVS_USERSPACE_ATTR_PID", "uint32"), 416e52b07aaSAaron Conole ("OVS_USERSPACE_ATTR_USERDATA", "array(uint8)"), 417e52b07aaSAaron Conole ("OVS_USERSPACE_ATTR_EGRESS_TUN_PORT", "uint32"), 418e52b07aaSAaron Conole ) 419e52b07aaSAaron Conole 420e52b07aaSAaron Conole def dpstr(self, more=False): 421e52b07aaSAaron Conole print_str = "userspace(" 422e52b07aaSAaron Conole if self.get_attr("OVS_USERSPACE_ATTR_PID") is not None: 423e52b07aaSAaron Conole print_str += "pid=%d," % self.get_attr( 424e52b07aaSAaron Conole "OVS_USERSPACE_ATTR_PID" 425e52b07aaSAaron Conole ) 426e52b07aaSAaron Conole if self.get_attr("OVS_USERSPACE_ATTR_USERDATA") is not None: 427e52b07aaSAaron Conole print_str += "userdata=" 428e52b07aaSAaron Conole for f in self.get_attr("OVS_USERSPACE_ATTR_USERDATA"): 429e52b07aaSAaron Conole print_str += "%x." % f 430e52b07aaSAaron Conole if self.get_attr("OVS_USERSPACE_ATTR_TUN_PORT") is not None: 431e52b07aaSAaron Conole print_str += "egress_tun_port=%d" % self.get_attr( 432e52b07aaSAaron Conole "OVS_USERSPACE_ATTR_TUN_PORT" 433e52b07aaSAaron Conole ) 434e52b07aaSAaron Conole print_str += ")" 435e52b07aaSAaron Conole return print_str 436e52b07aaSAaron Conole 437e52b07aaSAaron Conole def dpstr(self, more=False): 438e52b07aaSAaron Conole print_str = "" 439e52b07aaSAaron Conole 440e52b07aaSAaron Conole for field in self.nla_map: 441e52b07aaSAaron Conole if field[1] == "none" or self.get_attr(field[0]) is None: 442e52b07aaSAaron Conole continue 443e52b07aaSAaron Conole if print_str != "": 444e52b07aaSAaron Conole print_str += "," 445e52b07aaSAaron Conole 446e52b07aaSAaron Conole if field[1] == "uint32": 447e52b07aaSAaron Conole if field[0] == "OVS_ACTION_ATTR_OUTPUT": 448e52b07aaSAaron Conole print_str += "%d" % int(self.get_attr(field[0])) 449e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_RECIRC": 450e52b07aaSAaron Conole print_str += "recirc(0x%x)" % int(self.get_attr(field[0])) 451e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_TRUNC": 452e52b07aaSAaron Conole print_str += "trunc(%d)" % int(self.get_attr(field[0])) 453e7bc7db9SEric Garver elif field[0] == "OVS_ACTION_ATTR_DROP": 454e7bc7db9SEric Garver print_str += "drop(%d)" % int(self.get_attr(field[0])) 455e52b07aaSAaron Conole elif field[1] == "flag": 456e52b07aaSAaron Conole if field[0] == "OVS_ACTION_ATTR_CT_CLEAR": 457e52b07aaSAaron Conole print_str += "ct_clear" 458e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_POP_VLAN": 459e52b07aaSAaron Conole print_str += "pop_vlan" 460e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_POP_ETH": 461e52b07aaSAaron Conole print_str += "pop_eth" 462e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_POP_NSH": 463e52b07aaSAaron Conole print_str += "pop_nsh" 464e52b07aaSAaron Conole elif field[0] == "OVS_ACTION_ATTR_POP_MPLS": 465e52b07aaSAaron Conole print_str += "pop_mpls" 466e52b07aaSAaron Conole else: 467e52b07aaSAaron Conole datum = self.get_attr(field[0]) 4684c3157ddSAaron Conole if field[0] == "OVS_ACTION_ATTR_CLONE": 4694c3157ddSAaron Conole print_str += "clone(" 4704c3157ddSAaron Conole print_str += datum.dpstr(more) 4714c3157ddSAaron Conole print_str += ")" 4724c3157ddSAaron Conole else: 473e52b07aaSAaron Conole print_str += datum.dpstr(more) 474e52b07aaSAaron Conole 475e52b07aaSAaron Conole return print_str 476e52b07aaSAaron Conole 477918423fdSAaron Conole def parse(self, actstr): 4784c3157ddSAaron Conole totallen = len(actstr) 479918423fdSAaron Conole while len(actstr) != 0: 480918423fdSAaron Conole parsed = False 4814c3157ddSAaron Conole parencount = 0 482918423fdSAaron Conole if actstr.startswith("drop"): 483e7bc7db9SEric Garver # If no reason is provided, the implicit drop is used (i.e no 484e7bc7db9SEric Garver # action). If some reason is given, an explicit action is used. 4854c3157ddSAaron Conole reason = None 4864c3157ddSAaron Conole if actstr.startswith("drop("): 4874c3157ddSAaron Conole parencount += 1 4884c3157ddSAaron Conole 489e7bc7db9SEric Garver actstr, reason = parse_extract_field( 490e7bc7db9SEric Garver actstr, 491e7bc7db9SEric Garver "drop(", 492e7bc7db9SEric Garver "([0-9]+)", 493e7bc7db9SEric Garver lambda x: int(x, 0), 494e7bc7db9SEric Garver False, 495e7bc7db9SEric Garver None, 496e7bc7db9SEric Garver ) 4974c3157ddSAaron Conole 498e7bc7db9SEric Garver if reason is not None: 499e7bc7db9SEric Garver self["attrs"].append(["OVS_ACTION_ATTR_DROP", reason]) 500e7bc7db9SEric Garver parsed = True 501e7bc7db9SEric Garver else: 5024c3157ddSAaron Conole actstr = actstr[len("drop"): ] 5034c3157ddSAaron Conole return (totallen - len(actstr)) 504918423fdSAaron Conole 505918423fdSAaron Conole elif parse_starts_block(actstr, "^(\d+)", False, True): 506918423fdSAaron Conole actstr, output = parse_extract_field( 507918423fdSAaron Conole actstr, None, "(\d+)", lambda x: int(x), False, "0" 508918423fdSAaron Conole ) 509918423fdSAaron Conole self["attrs"].append(["OVS_ACTION_ATTR_OUTPUT", output]) 510918423fdSAaron Conole parsed = True 511918423fdSAaron Conole elif parse_starts_block(actstr, "recirc(", False): 512918423fdSAaron Conole actstr, recircid = parse_extract_field( 513918423fdSAaron Conole actstr, 514918423fdSAaron Conole "recirc(", 515918423fdSAaron Conole "([0-9a-fA-Fx]+)", 516918423fdSAaron Conole lambda x: int(x, 0), 517918423fdSAaron Conole False, 518918423fdSAaron Conole 0, 519918423fdSAaron Conole ) 5204c3157ddSAaron Conole parencount += 1 521918423fdSAaron Conole self["attrs"].append(["OVS_ACTION_ATTR_RECIRC", recircid]) 522918423fdSAaron Conole parsed = True 523918423fdSAaron Conole 524918423fdSAaron Conole parse_flat_map = ( 525918423fdSAaron Conole ("ct_clear", "OVS_ACTION_ATTR_CT_CLEAR"), 526918423fdSAaron Conole ("pop_vlan", "OVS_ACTION_ATTR_POP_VLAN"), 527918423fdSAaron Conole ("pop_eth", "OVS_ACTION_ATTR_POP_ETH"), 528918423fdSAaron Conole ("pop_nsh", "OVS_ACTION_ATTR_POP_NSH"), 529918423fdSAaron Conole ) 530918423fdSAaron Conole 531918423fdSAaron Conole for flat_act in parse_flat_map: 532918423fdSAaron Conole if parse_starts_block(actstr, flat_act[0], False): 5334c3157ddSAaron Conole actstr = actstr[len(flat_act[0]):] 534*c436a235SAdrian Moreno self["attrs"].append([flat_act[1], True]) 535918423fdSAaron Conole actstr = actstr[strspn(actstr, ", ") :] 536918423fdSAaron Conole parsed = True 537918423fdSAaron Conole 5384c3157ddSAaron Conole if parse_starts_block(actstr, "clone(", False): 5394c3157ddSAaron Conole parencount += 1 5404c3157ddSAaron Conole subacts = ovsactions() 5414c3157ddSAaron Conole actstr = actstr[len("clone("):] 5424c3157ddSAaron Conole parsedLen = subacts.parse(actstr) 5434c3157ddSAaron Conole lst = [] 5444c3157ddSAaron Conole self["attrs"].append(("OVS_ACTION_ATTR_CLONE", subacts)) 5454c3157ddSAaron Conole actstr = actstr[parsedLen:] 5464c3157ddSAaron Conole parsed = True 5474c3157ddSAaron Conole elif parse_starts_block(actstr, "ct(", False): 5484c3157ddSAaron Conole parencount += 1 5492893ba9cSAaron Conole actstr = actstr[len("ct(") :] 5502893ba9cSAaron Conole ctact = ovsactions.ctact() 5512893ba9cSAaron Conole 5522893ba9cSAaron Conole for scan in ( 5532893ba9cSAaron Conole ("commit", "OVS_CT_ATTR_COMMIT", None), 5542893ba9cSAaron Conole ("force_commit", "OVS_CT_ATTR_FORCE_COMMIT", None), 5552893ba9cSAaron Conole ("zone", "OVS_CT_ATTR_ZONE", int), 5562893ba9cSAaron Conole ("mark", "OVS_CT_ATTR_MARK", int), 5572893ba9cSAaron Conole ("helper", "OVS_CT_ATTR_HELPER", lambda x, y: str(x)), 5582893ba9cSAaron Conole ("timeout", "OVS_CT_ATTR_TIMEOUT", lambda x, y: str(x)), 5592893ba9cSAaron Conole ): 5602893ba9cSAaron Conole if actstr.startswith(scan[0]): 5612893ba9cSAaron Conole actstr = actstr[len(scan[0]) :] 5622893ba9cSAaron Conole if scan[2] is not None: 5632893ba9cSAaron Conole if actstr[0] != "=": 5642893ba9cSAaron Conole raise ValueError("Invalid ct attr") 5652893ba9cSAaron Conole actstr = actstr[1:] 5662893ba9cSAaron Conole pos = strcspn(actstr, ",)") 5672893ba9cSAaron Conole datum = scan[2](actstr[:pos], 0) 5682893ba9cSAaron Conole ctact["attrs"].append([scan[1], datum]) 5692893ba9cSAaron Conole actstr = actstr[pos:] 5702893ba9cSAaron Conole else: 5712893ba9cSAaron Conole ctact["attrs"].append([scan[1], None]) 5722893ba9cSAaron Conole actstr = actstr[strspn(actstr, ", ") :] 57360f10077SAaron Conole # it seems strange to put this here, but nat() is a complex 57460f10077SAaron Conole # sub-action and this lets it sit anywhere in the ct() action 57560f10077SAaron Conole if actstr.startswith("nat"): 57660f10077SAaron Conole actstr = actstr[3:] 57760f10077SAaron Conole natact = ovsactions.ctact.natattr() 57860f10077SAaron Conole 57960f10077SAaron Conole if actstr.startswith("("): 5804c3157ddSAaron Conole parencount += 1 58160f10077SAaron Conole t = None 58260f10077SAaron Conole actstr = actstr[1:] 58360f10077SAaron Conole if actstr.startswith("src"): 58460f10077SAaron Conole t = "OVS_NAT_ATTR_SRC" 58560f10077SAaron Conole actstr = actstr[3:] 58660f10077SAaron Conole elif actstr.startswith("dst"): 58760f10077SAaron Conole t = "OVS_NAT_ATTR_DST" 58860f10077SAaron Conole actstr = actstr[3:] 58960f10077SAaron Conole 59060f10077SAaron Conole actstr, ip_block_min = parse_extract_field( 59160f10077SAaron Conole actstr, "=", "([0-9a-fA-F\.]+)", str, False 59260f10077SAaron Conole ) 59360f10077SAaron Conole actstr, ip_block_max = parse_extract_field( 59460f10077SAaron Conole actstr, "-", "([0-9a-fA-F\.]+)", str, False 59560f10077SAaron Conole ) 59660f10077SAaron Conole 59760f10077SAaron Conole actstr, proto_min = parse_extract_field( 59860f10077SAaron Conole actstr, ":", "(\d+)", int, False 59960f10077SAaron Conole ) 60060f10077SAaron Conole actstr, proto_max = parse_extract_field( 60160f10077SAaron Conole actstr, "-", "(\d+)", int, False 60260f10077SAaron Conole ) 60360f10077SAaron Conole 60460f10077SAaron Conole if t is not None: 60560f10077SAaron Conole natact["attrs"].append([t, None]) 60660f10077SAaron Conole 60760f10077SAaron Conole if ip_block_min is not None: 60860f10077SAaron Conole natact["attrs"].append( 60960f10077SAaron Conole ["OVS_NAT_ATTR_IP_MIN", ip_block_min] 61060f10077SAaron Conole ) 61160f10077SAaron Conole if ip_block_max is not None: 61260f10077SAaron Conole natact["attrs"].append( 61360f10077SAaron Conole ["OVS_NAT_ATTR_IP_MAX", ip_block_max] 61460f10077SAaron Conole ) 61560f10077SAaron Conole if proto_min is not None: 61660f10077SAaron Conole natact["attrs"].append( 61760f10077SAaron Conole ["OVS_NAT_ATTR_PROTO_MIN", proto_min] 61860f10077SAaron Conole ) 61960f10077SAaron Conole if proto_max is not None: 62060f10077SAaron Conole natact["attrs"].append( 62160f10077SAaron Conole ["OVS_NAT_ATTR_PROTO_MAX", proto_max] 62260f10077SAaron Conole ) 62360f10077SAaron Conole 62460f10077SAaron Conole for natscan in ( 62560f10077SAaron Conole ("persistent", "OVS_NAT_ATTR_PERSISTENT"), 62660f10077SAaron Conole ("hash", "OVS_NAT_ATTR_PROTO_HASH"), 62760f10077SAaron Conole ("random", "OVS_NAT_ATTR_PROTO_RANDOM"), 62860f10077SAaron Conole ): 62960f10077SAaron Conole if actstr.startswith(natscan[0]): 63060f10077SAaron Conole actstr = actstr[len(natscan[0]) :] 63160f10077SAaron Conole natact["attrs"].append([natscan[1], None]) 63260f10077SAaron Conole actstr = actstr[strspn(actstr, ", ") :] 63360f10077SAaron Conole 63460f10077SAaron Conole ctact["attrs"].append(["OVS_CT_ATTR_NAT", natact]) 6354c3157ddSAaron Conole actstr = actstr[strspn(actstr, ", ") :] 6362893ba9cSAaron Conole 6372893ba9cSAaron Conole self["attrs"].append(["OVS_ACTION_ATTR_CT", ctact]) 6382893ba9cSAaron Conole parsed = True 6392893ba9cSAaron Conole 6404c3157ddSAaron Conole actstr = actstr[strspn(actstr, ", ") :] 6414c3157ddSAaron Conole while parencount > 0: 6424c3157ddSAaron Conole parencount -= 1 6434c3157ddSAaron Conole actstr = actstr[strspn(actstr, " "):] 6444c3157ddSAaron Conole if len(actstr) and actstr[0] != ")": 6454c3157ddSAaron Conole raise ValueError("Action str: '%s' unbalanced" % actstr) 6464c3157ddSAaron Conole actstr = actstr[1:] 6474c3157ddSAaron Conole 6484c3157ddSAaron Conole if len(actstr) and actstr[0] == ")": 6494c3157ddSAaron Conole return (totallen - len(actstr)) 6504c3157ddSAaron Conole 6514c3157ddSAaron Conole actstr = actstr[strspn(actstr, ", ") :] 6524c3157ddSAaron Conole 653918423fdSAaron Conole if not parsed: 654918423fdSAaron Conole raise ValueError("Action str: '%s' not supported" % actstr) 655918423fdSAaron Conole 6564c3157ddSAaron Conole return (totallen - len(actstr)) 6574c3157ddSAaron Conole 658e52b07aaSAaron Conole 659e52b07aaSAaron Conoleclass ovskey(nla): 660e52b07aaSAaron Conole nla_flags = NLA_F_NESTED 661e52b07aaSAaron Conole nla_map = ( 662e52b07aaSAaron Conole ("OVS_KEY_ATTR_UNSPEC", "none"), 663e52b07aaSAaron Conole ("OVS_KEY_ATTR_ENCAP", "none"), 664e52b07aaSAaron Conole ("OVS_KEY_ATTR_PRIORITY", "uint32"), 665e52b07aaSAaron Conole ("OVS_KEY_ATTR_IN_PORT", "uint32"), 666e52b07aaSAaron Conole ("OVS_KEY_ATTR_ETHERNET", "ethaddr"), 667e52b07aaSAaron Conole ("OVS_KEY_ATTR_VLAN", "uint16"), 668e52b07aaSAaron Conole ("OVS_KEY_ATTR_ETHERTYPE", "be16"), 669e52b07aaSAaron Conole ("OVS_KEY_ATTR_IPV4", "ovs_key_ipv4"), 670e52b07aaSAaron Conole ("OVS_KEY_ATTR_IPV6", "ovs_key_ipv6"), 671e52b07aaSAaron Conole ("OVS_KEY_ATTR_TCP", "ovs_key_tcp"), 672e52b07aaSAaron Conole ("OVS_KEY_ATTR_UDP", "ovs_key_udp"), 673e52b07aaSAaron Conole ("OVS_KEY_ATTR_ICMP", "ovs_key_icmp"), 674e52b07aaSAaron Conole ("OVS_KEY_ATTR_ICMPV6", "ovs_key_icmpv6"), 675e52b07aaSAaron Conole ("OVS_KEY_ATTR_ARP", "ovs_key_arp"), 676e52b07aaSAaron Conole ("OVS_KEY_ATTR_ND", "ovs_key_nd"), 677e52b07aaSAaron Conole ("OVS_KEY_ATTR_SKB_MARK", "uint32"), 678e52b07aaSAaron Conole ("OVS_KEY_ATTR_TUNNEL", "none"), 679e52b07aaSAaron Conole ("OVS_KEY_ATTR_SCTP", "ovs_key_sctp"), 680e52b07aaSAaron Conole ("OVS_KEY_ATTR_TCP_FLAGS", "be16"), 681e52b07aaSAaron Conole ("OVS_KEY_ATTR_DP_HASH", "uint32"), 682e52b07aaSAaron Conole ("OVS_KEY_ATTR_RECIRC_ID", "uint32"), 683e52b07aaSAaron Conole ("OVS_KEY_ATTR_MPLS", "array(ovs_key_mpls)"), 684e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_STATE", "uint32"), 685e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_ZONE", "uint16"), 686e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_MARK", "uint32"), 687e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_LABELS", "none"), 688e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", "ovs_key_ct_tuple_ipv4"), 689e52b07aaSAaron Conole ("OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", "ovs_key_ct_tuple_ipv6"), 690e52b07aaSAaron Conole ("OVS_KEY_ATTR_NSH", "none"), 691e52b07aaSAaron Conole ("OVS_KEY_ATTR_PACKET_TYPE", "none"), 692e52b07aaSAaron Conole ("OVS_KEY_ATTR_ND_EXTENSIONS", "none"), 693e52b07aaSAaron Conole ("OVS_KEY_ATTR_TUNNEL_INFO", "none"), 694e52b07aaSAaron Conole ("OVS_KEY_ATTR_IPV6_EXTENSIONS", "none"), 695e52b07aaSAaron Conole ) 696e52b07aaSAaron Conole 697e52b07aaSAaron Conole class ovs_key_proto(nla): 698e52b07aaSAaron Conole fields = ( 699e52b07aaSAaron Conole ("src", "!H"), 700e52b07aaSAaron Conole ("dst", "!H"), 701e52b07aaSAaron Conole ) 702e52b07aaSAaron Conole 703e52b07aaSAaron Conole fields_map = ( 7049f1179fbSAdrian Moreno ("src", "src", "%d", lambda x: int(x) if x else 0, 7059f1179fbSAdrian Moreno convert_int(16)), 7069f1179fbSAdrian Moreno ("dst", "dst", "%d", lambda x: int(x) if x else 0, 7079f1179fbSAdrian Moreno convert_int(16)), 708e52b07aaSAaron Conole ) 709e52b07aaSAaron Conole 710e52b07aaSAaron Conole def __init__( 711e52b07aaSAaron Conole self, 712e52b07aaSAaron Conole protostr, 713e52b07aaSAaron Conole data=None, 714e52b07aaSAaron Conole offset=None, 715e52b07aaSAaron Conole parent=None, 716e52b07aaSAaron Conole length=None, 717e52b07aaSAaron Conole init=None, 718e52b07aaSAaron Conole ): 719e52b07aaSAaron Conole self.proto_str = protostr 720e52b07aaSAaron Conole nla.__init__( 721e52b07aaSAaron Conole self, 722e52b07aaSAaron Conole data=data, 723e52b07aaSAaron Conole offset=offset, 724e52b07aaSAaron Conole parent=parent, 725e52b07aaSAaron Conole length=length, 726e52b07aaSAaron Conole init=init, 727e52b07aaSAaron Conole ) 728e52b07aaSAaron Conole 729918423fdSAaron Conole def parse(self, flowstr, typeInst): 730918423fdSAaron Conole if not flowstr.startswith(self.proto_str): 731918423fdSAaron Conole return None, None 732918423fdSAaron Conole 733918423fdSAaron Conole k = typeInst() 734918423fdSAaron Conole m = typeInst() 735918423fdSAaron Conole 736918423fdSAaron Conole flowstr = flowstr[len(self.proto_str) :] 737918423fdSAaron Conole if flowstr.startswith("("): 738918423fdSAaron Conole flowstr = flowstr[1:] 739918423fdSAaron Conole 740918423fdSAaron Conole keybits = b"" 741918423fdSAaron Conole maskbits = b"" 742918423fdSAaron Conole for f in self.fields_map: 743918423fdSAaron Conole if flowstr.startswith(f[1]): 744918423fdSAaron Conole # the following assumes that the field looks 745918423fdSAaron Conole # something like 'field.' where '.' is a 746918423fdSAaron Conole # character that we don't exactly care about. 747918423fdSAaron Conole flowstr = flowstr[len(f[1]) + 1 :] 748918423fdSAaron Conole splitchar = 0 749918423fdSAaron Conole for c in flowstr: 750918423fdSAaron Conole if c == "," or c == ")": 751918423fdSAaron Conole break 752918423fdSAaron Conole splitchar += 1 753918423fdSAaron Conole data = flowstr[:splitchar] 754918423fdSAaron Conole flowstr = flowstr[splitchar:] 755918423fdSAaron Conole else: 7569f1179fbSAdrian Moreno data = "" 757918423fdSAaron Conole 758918423fdSAaron Conole if len(f) > 4: 7599f1179fbSAdrian Moreno k[f[0]], m[f[0]] = f[4](data) 760918423fdSAaron Conole else: 7619f1179fbSAdrian Moreno k[f[0]] = f[3](data) 7629f1179fbSAdrian Moreno m[f[0]] = f[3](data) 763918423fdSAaron Conole 764918423fdSAaron Conole flowstr = flowstr[strspn(flowstr, ", ") :] 765918423fdSAaron Conole if len(flowstr) == 0: 766918423fdSAaron Conole return flowstr, k, m 767918423fdSAaron Conole 768918423fdSAaron Conole flowstr = flowstr[strspn(flowstr, "), ") :] 769918423fdSAaron Conole 770918423fdSAaron Conole return flowstr, k, m 771918423fdSAaron Conole 772e52b07aaSAaron Conole def dpstr(self, masked=None, more=False): 773e52b07aaSAaron Conole outstr = self.proto_str + "(" 774e52b07aaSAaron Conole first = False 775e52b07aaSAaron Conole for f in self.fields_map: 776e52b07aaSAaron Conole if first: 777e52b07aaSAaron Conole outstr += "," 778e52b07aaSAaron Conole if masked is None: 779e52b07aaSAaron Conole outstr += "%s=" % f[0] 780e52b07aaSAaron Conole if isinstance(f[2], str): 781e52b07aaSAaron Conole outstr += f[2] % self[f[1]] 782e52b07aaSAaron Conole else: 783e52b07aaSAaron Conole outstr += f[2](self[f[1]]) 784e52b07aaSAaron Conole first = True 785e52b07aaSAaron Conole elif more or f[3](masked[f[1]]) != 0: 786e52b07aaSAaron Conole outstr += "%s=" % f[0] 787e52b07aaSAaron Conole if isinstance(f[2], str): 788e52b07aaSAaron Conole outstr += f[2] % self[f[1]] 789e52b07aaSAaron Conole else: 790e52b07aaSAaron Conole outstr += f[2](self[f[1]]) 791e52b07aaSAaron Conole outstr += "/" 792e52b07aaSAaron Conole if isinstance(f[2], str): 793e52b07aaSAaron Conole outstr += f[2] % masked[f[1]] 794e52b07aaSAaron Conole else: 795e52b07aaSAaron Conole outstr += f[2](masked[f[1]]) 796e52b07aaSAaron Conole first = True 797e52b07aaSAaron Conole outstr += ")" 798e52b07aaSAaron Conole return outstr 799e52b07aaSAaron Conole 800e52b07aaSAaron Conole class ethaddr(ovs_key_proto): 801e52b07aaSAaron Conole fields = ( 802e52b07aaSAaron Conole ("src", "!6s"), 803e52b07aaSAaron Conole ("dst", "!6s"), 804e52b07aaSAaron Conole ) 805e52b07aaSAaron Conole 806e52b07aaSAaron Conole fields_map = ( 807e52b07aaSAaron Conole ( 808e52b07aaSAaron Conole "src", 809e52b07aaSAaron Conole "src", 810e52b07aaSAaron Conole macstr, 811e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 812e52b07aaSAaron Conole convert_mac, 813e52b07aaSAaron Conole ), 814e52b07aaSAaron Conole ( 815e52b07aaSAaron Conole "dst", 816e52b07aaSAaron Conole "dst", 817e52b07aaSAaron Conole macstr, 818e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 819e52b07aaSAaron Conole convert_mac, 820e52b07aaSAaron Conole ), 821e52b07aaSAaron Conole ) 822e52b07aaSAaron Conole 823e52b07aaSAaron Conole def __init__( 824e52b07aaSAaron Conole self, 825e52b07aaSAaron Conole data=None, 826e52b07aaSAaron Conole offset=None, 827e52b07aaSAaron Conole parent=None, 828e52b07aaSAaron Conole length=None, 829e52b07aaSAaron Conole init=None, 830e52b07aaSAaron Conole ): 831e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 832e52b07aaSAaron Conole self, 833e52b07aaSAaron Conole "eth", 834e52b07aaSAaron Conole data=data, 835e52b07aaSAaron Conole offset=offset, 836e52b07aaSAaron Conole parent=parent, 837e52b07aaSAaron Conole length=length, 838e52b07aaSAaron Conole init=init, 839e52b07aaSAaron Conole ) 840e52b07aaSAaron Conole 841e52b07aaSAaron Conole class ovs_key_ipv4(ovs_key_proto): 842e52b07aaSAaron Conole fields = ( 843e52b07aaSAaron Conole ("src", "!I"), 844e52b07aaSAaron Conole ("dst", "!I"), 845e52b07aaSAaron Conole ("proto", "B"), 846e52b07aaSAaron Conole ("tos", "B"), 847e52b07aaSAaron Conole ("ttl", "B"), 848e52b07aaSAaron Conole ("frag", "B"), 849e52b07aaSAaron Conole ) 850e52b07aaSAaron Conole 851e52b07aaSAaron Conole fields_map = ( 852e52b07aaSAaron Conole ( 853e52b07aaSAaron Conole "src", 854e52b07aaSAaron Conole "src", 855e52b07aaSAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 856e52b07aaSAaron Conole int, 857e52b07aaSAaron Conole convert_ipv4, 858e52b07aaSAaron Conole ), 859e52b07aaSAaron Conole ( 860e52b07aaSAaron Conole "dst", 861e52b07aaSAaron Conole "dst", 862e52b07aaSAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 863e52b07aaSAaron Conole int, 864e52b07aaSAaron Conole convert_ipv4, 865e52b07aaSAaron Conole ), 8669f1179fbSAdrian Moreno ("proto", "proto", "%d", lambda x: int(x) if x else 0, 8679f1179fbSAdrian Moreno convert_int(8)), 8689f1179fbSAdrian Moreno ("tos", "tos", "%d", lambda x: int(x) if x else 0, 8699f1179fbSAdrian Moreno convert_int(8)), 8709f1179fbSAdrian Moreno ("ttl", "ttl", "%d", lambda x: int(x) if x else 0, 8719f1179fbSAdrian Moreno convert_int(8)), 8729f1179fbSAdrian Moreno ("frag", "frag", "%d", lambda x: int(x) if x else 0, 8739f1179fbSAdrian Moreno convert_int(8)), 874e52b07aaSAaron Conole ) 875e52b07aaSAaron Conole 876e52b07aaSAaron Conole def __init__( 877e52b07aaSAaron Conole self, 878e52b07aaSAaron Conole data=None, 879e52b07aaSAaron Conole offset=None, 880e52b07aaSAaron Conole parent=None, 881e52b07aaSAaron Conole length=None, 882e52b07aaSAaron Conole init=None, 883e52b07aaSAaron Conole ): 884e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 885e52b07aaSAaron Conole self, 886e52b07aaSAaron Conole "ipv4", 887e52b07aaSAaron Conole data=data, 888e52b07aaSAaron Conole offset=offset, 889e52b07aaSAaron Conole parent=parent, 890e52b07aaSAaron Conole length=length, 891e52b07aaSAaron Conole init=init, 892e52b07aaSAaron Conole ) 893e52b07aaSAaron Conole 894e52b07aaSAaron Conole class ovs_key_ipv6(ovs_key_proto): 895e52b07aaSAaron Conole fields = ( 896e52b07aaSAaron Conole ("src", "!16s"), 897e52b07aaSAaron Conole ("dst", "!16s"), 898e52b07aaSAaron Conole ("label", "!I"), 899e52b07aaSAaron Conole ("proto", "B"), 900e52b07aaSAaron Conole ("tclass", "B"), 901e52b07aaSAaron Conole ("hlimit", "B"), 902e52b07aaSAaron Conole ("frag", "B"), 903e52b07aaSAaron Conole ) 904e52b07aaSAaron Conole 905e52b07aaSAaron Conole fields_map = ( 906e52b07aaSAaron Conole ( 907e52b07aaSAaron Conole "src", 908e52b07aaSAaron Conole "src", 909e52b07aaSAaron Conole lambda x: str(ipaddress.IPv6Address(x)), 910e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 911e52b07aaSAaron Conole lambda x: ipaddress.IPv6Address(x), 912e52b07aaSAaron Conole ), 913e52b07aaSAaron Conole ( 914e52b07aaSAaron Conole "dst", 915e52b07aaSAaron Conole "dst", 916e52b07aaSAaron Conole lambda x: str(ipaddress.IPv6Address(x)), 917e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 918e52b07aaSAaron Conole lambda x: ipaddress.IPv6Address(x), 919e52b07aaSAaron Conole ), 920e52b07aaSAaron Conole ("label", "label", "%d", int), 921e52b07aaSAaron Conole ("proto", "proto", "%d", int), 922e52b07aaSAaron Conole ("tclass", "tclass", "%d", int), 923e52b07aaSAaron Conole ("hlimit", "hlimit", "%d", int), 924e52b07aaSAaron Conole ("frag", "frag", "%d", int), 925e52b07aaSAaron Conole ) 926e52b07aaSAaron Conole 927e52b07aaSAaron Conole def __init__( 928e52b07aaSAaron Conole self, 929e52b07aaSAaron Conole data=None, 930e52b07aaSAaron Conole offset=None, 931e52b07aaSAaron Conole parent=None, 932e52b07aaSAaron Conole length=None, 933e52b07aaSAaron Conole init=None, 934e52b07aaSAaron Conole ): 935e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 936e52b07aaSAaron Conole self, 937e52b07aaSAaron Conole "ipv6", 938e52b07aaSAaron Conole data=data, 939e52b07aaSAaron Conole offset=offset, 940e52b07aaSAaron Conole parent=parent, 941e52b07aaSAaron Conole length=length, 942e52b07aaSAaron Conole init=init, 943e52b07aaSAaron Conole ) 944e52b07aaSAaron Conole 945e52b07aaSAaron Conole class ovs_key_tcp(ovs_key_proto): 946e52b07aaSAaron Conole def __init__( 947e52b07aaSAaron Conole self, 948e52b07aaSAaron Conole data=None, 949e52b07aaSAaron Conole offset=None, 950e52b07aaSAaron Conole parent=None, 951e52b07aaSAaron Conole length=None, 952e52b07aaSAaron Conole init=None, 953e52b07aaSAaron Conole ): 954e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 955e52b07aaSAaron Conole self, 956e52b07aaSAaron Conole "tcp", 957e52b07aaSAaron Conole data=data, 958e52b07aaSAaron Conole offset=offset, 959e52b07aaSAaron Conole parent=parent, 960e52b07aaSAaron Conole length=length, 961e52b07aaSAaron Conole init=init, 962e52b07aaSAaron Conole ) 963e52b07aaSAaron Conole 964e52b07aaSAaron Conole class ovs_key_udp(ovs_key_proto): 965e52b07aaSAaron Conole def __init__( 966e52b07aaSAaron Conole self, 967e52b07aaSAaron Conole data=None, 968e52b07aaSAaron Conole offset=None, 969e52b07aaSAaron Conole parent=None, 970e52b07aaSAaron Conole length=None, 971e52b07aaSAaron Conole init=None, 972e52b07aaSAaron Conole ): 973e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 974e52b07aaSAaron Conole self, 975e52b07aaSAaron Conole "udp", 976e52b07aaSAaron Conole data=data, 977e52b07aaSAaron Conole offset=offset, 978e52b07aaSAaron Conole parent=parent, 979e52b07aaSAaron Conole length=length, 980e52b07aaSAaron Conole init=init, 981e52b07aaSAaron Conole ) 982e52b07aaSAaron Conole 983e52b07aaSAaron Conole class ovs_key_sctp(ovs_key_proto): 984e52b07aaSAaron Conole def __init__( 985e52b07aaSAaron Conole self, 986e52b07aaSAaron Conole data=None, 987e52b07aaSAaron Conole offset=None, 988e52b07aaSAaron Conole parent=None, 989e52b07aaSAaron Conole length=None, 990e52b07aaSAaron Conole init=None, 991e52b07aaSAaron Conole ): 992e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 993e52b07aaSAaron Conole self, 994e52b07aaSAaron Conole "sctp", 995e52b07aaSAaron Conole data=data, 996e52b07aaSAaron Conole offset=offset, 997e52b07aaSAaron Conole parent=parent, 998e52b07aaSAaron Conole length=length, 999e52b07aaSAaron Conole init=init, 1000e52b07aaSAaron Conole ) 1001e52b07aaSAaron Conole 1002e52b07aaSAaron Conole class ovs_key_icmp(ovs_key_proto): 1003e52b07aaSAaron Conole fields = ( 1004e52b07aaSAaron Conole ("type", "B"), 1005e52b07aaSAaron Conole ("code", "B"), 1006e52b07aaSAaron Conole ) 1007e52b07aaSAaron Conole 1008e52b07aaSAaron Conole fields_map = ( 10099f1179fbSAdrian Moreno ("type", "type", "%d", lambda x: int(x) if x else 0), 10109f1179fbSAdrian Moreno ("code", "code", "%d", lambda x: int(x) if x else 0), 1011e52b07aaSAaron Conole ) 1012e52b07aaSAaron Conole 1013e52b07aaSAaron Conole def __init__( 1014e52b07aaSAaron Conole self, 1015e52b07aaSAaron Conole data=None, 1016e52b07aaSAaron Conole offset=None, 1017e52b07aaSAaron Conole parent=None, 1018e52b07aaSAaron Conole length=None, 1019e52b07aaSAaron Conole init=None, 1020e52b07aaSAaron Conole ): 1021e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1022e52b07aaSAaron Conole self, 1023e52b07aaSAaron Conole "icmp", 1024e52b07aaSAaron Conole data=data, 1025e52b07aaSAaron Conole offset=offset, 1026e52b07aaSAaron Conole parent=parent, 1027e52b07aaSAaron Conole length=length, 1028e52b07aaSAaron Conole init=init, 1029e52b07aaSAaron Conole ) 1030e52b07aaSAaron Conole 1031e52b07aaSAaron Conole class ovs_key_icmpv6(ovs_key_icmp): 1032e52b07aaSAaron Conole def __init__( 1033e52b07aaSAaron Conole self, 1034e52b07aaSAaron Conole data=None, 1035e52b07aaSAaron Conole offset=None, 1036e52b07aaSAaron Conole parent=None, 1037e52b07aaSAaron Conole length=None, 1038e52b07aaSAaron Conole init=None, 1039e52b07aaSAaron Conole ): 1040e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1041e52b07aaSAaron Conole self, 1042e52b07aaSAaron Conole "icmpv6", 1043e52b07aaSAaron Conole data=data, 1044e52b07aaSAaron Conole offset=offset, 1045e52b07aaSAaron Conole parent=parent, 1046e52b07aaSAaron Conole length=length, 1047e52b07aaSAaron Conole init=init, 1048e52b07aaSAaron Conole ) 1049e52b07aaSAaron Conole 1050e52b07aaSAaron Conole class ovs_key_arp(ovs_key_proto): 1051e52b07aaSAaron Conole fields = ( 1052e52b07aaSAaron Conole ("sip", "!I"), 1053e52b07aaSAaron Conole ("tip", "!I"), 1054e52b07aaSAaron Conole ("op", "!H"), 1055e52b07aaSAaron Conole ("sha", "!6s"), 1056e52b07aaSAaron Conole ("tha", "!6s"), 1057e52b07aaSAaron Conole ("pad", "xx"), 1058e52b07aaSAaron Conole ) 1059e52b07aaSAaron Conole 1060e52b07aaSAaron Conole fields_map = ( 1061e52b07aaSAaron Conole ( 1062e52b07aaSAaron Conole "sip", 1063e52b07aaSAaron Conole "sip", 1064e52b07aaSAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 1065e52b07aaSAaron Conole int, 1066e52b07aaSAaron Conole convert_ipv4, 1067e52b07aaSAaron Conole ), 1068e52b07aaSAaron Conole ( 1069e52b07aaSAaron Conole "tip", 1070e52b07aaSAaron Conole "tip", 1071e52b07aaSAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 1072e52b07aaSAaron Conole int, 1073e52b07aaSAaron Conole convert_ipv4, 1074e52b07aaSAaron Conole ), 10759f1179fbSAdrian Moreno ("op", "op", "%d", lambda x: int(x) if x else 0), 1076e52b07aaSAaron Conole ( 1077e52b07aaSAaron Conole "sha", 1078e52b07aaSAaron Conole "sha", 1079e52b07aaSAaron Conole macstr, 1080e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 1081e52b07aaSAaron Conole convert_mac, 1082e52b07aaSAaron Conole ), 1083e52b07aaSAaron Conole ( 1084e52b07aaSAaron Conole "tha", 1085e52b07aaSAaron Conole "tha", 1086e52b07aaSAaron Conole macstr, 1087e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 1088e52b07aaSAaron Conole convert_mac, 1089e52b07aaSAaron Conole ), 1090e52b07aaSAaron Conole ) 1091e52b07aaSAaron Conole 1092e52b07aaSAaron Conole def __init__( 1093e52b07aaSAaron Conole self, 1094e52b07aaSAaron Conole data=None, 1095e52b07aaSAaron Conole offset=None, 1096e52b07aaSAaron Conole parent=None, 1097e52b07aaSAaron Conole length=None, 1098e52b07aaSAaron Conole init=None, 1099e52b07aaSAaron Conole ): 1100e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1101e52b07aaSAaron Conole self, 1102e52b07aaSAaron Conole "arp", 1103e52b07aaSAaron Conole data=data, 1104e52b07aaSAaron Conole offset=offset, 1105e52b07aaSAaron Conole parent=parent, 1106e52b07aaSAaron Conole length=length, 1107e52b07aaSAaron Conole init=init, 1108e52b07aaSAaron Conole ) 1109e52b07aaSAaron Conole 1110e52b07aaSAaron Conole class ovs_key_nd(ovs_key_proto): 1111e52b07aaSAaron Conole fields = ( 1112e52b07aaSAaron Conole ("target", "!16s"), 1113e52b07aaSAaron Conole ("sll", "!6s"), 1114e52b07aaSAaron Conole ("tll", "!6s"), 1115e52b07aaSAaron Conole ) 1116e52b07aaSAaron Conole 1117e52b07aaSAaron Conole fields_map = ( 1118e52b07aaSAaron Conole ( 1119e52b07aaSAaron Conole "target", 1120e52b07aaSAaron Conole "target", 1121e52b07aaSAaron Conole lambda x: str(ipaddress.IPv6Address(x)), 1122e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 1123e52b07aaSAaron Conole ), 1124e52b07aaSAaron Conole ("sll", "sll", macstr, lambda x: int.from_bytes(x, "big")), 1125e52b07aaSAaron Conole ("tll", "tll", macstr, lambda x: int.from_bytes(x, "big")), 1126e52b07aaSAaron Conole ) 1127e52b07aaSAaron Conole 1128e52b07aaSAaron Conole def __init__( 1129e52b07aaSAaron Conole self, 1130e52b07aaSAaron Conole data=None, 1131e52b07aaSAaron Conole offset=None, 1132e52b07aaSAaron Conole parent=None, 1133e52b07aaSAaron Conole length=None, 1134e52b07aaSAaron Conole init=None, 1135e52b07aaSAaron Conole ): 1136e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1137e52b07aaSAaron Conole self, 1138e52b07aaSAaron Conole "nd", 1139e52b07aaSAaron Conole data=data, 1140e52b07aaSAaron Conole offset=offset, 1141e52b07aaSAaron Conole parent=parent, 1142e52b07aaSAaron Conole length=length, 1143e52b07aaSAaron Conole init=init, 1144e52b07aaSAaron Conole ) 1145e52b07aaSAaron Conole 1146e52b07aaSAaron Conole class ovs_key_ct_tuple_ipv4(ovs_key_proto): 1147e52b07aaSAaron Conole fields = ( 1148e52b07aaSAaron Conole ("src", "!I"), 1149e52b07aaSAaron Conole ("dst", "!I"), 1150e52b07aaSAaron Conole ("tp_src", "!H"), 1151e52b07aaSAaron Conole ("tp_dst", "!H"), 1152e52b07aaSAaron Conole ("proto", "B"), 1153e52b07aaSAaron Conole ) 1154e52b07aaSAaron Conole 1155e52b07aaSAaron Conole fields_map = ( 1156e52b07aaSAaron Conole ( 1157e52b07aaSAaron Conole "src", 1158e52b07aaSAaron Conole "src", 1159e52b07aaSAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 1160e52b07aaSAaron Conole int, 11618eff0e06SAaron Conole convert_ipv4, 1162e52b07aaSAaron Conole ), 1163e52b07aaSAaron Conole ( 1164e52b07aaSAaron Conole "dst", 1165e52b07aaSAaron Conole "dst", 11668eff0e06SAaron Conole lambda x: str(ipaddress.IPv4Address(x)), 1167e52b07aaSAaron Conole int, 11688eff0e06SAaron Conole convert_ipv4, 1169e52b07aaSAaron Conole ), 1170e52b07aaSAaron Conole ("tp_src", "tp_src", "%d", int), 1171e52b07aaSAaron Conole ("tp_dst", "tp_dst", "%d", int), 1172e52b07aaSAaron Conole ("proto", "proto", "%d", int), 1173e52b07aaSAaron Conole ) 1174e52b07aaSAaron Conole 1175e52b07aaSAaron Conole def __init__( 1176e52b07aaSAaron Conole self, 1177e52b07aaSAaron Conole data=None, 1178e52b07aaSAaron Conole offset=None, 1179e52b07aaSAaron Conole parent=None, 1180e52b07aaSAaron Conole length=None, 1181e52b07aaSAaron Conole init=None, 1182e52b07aaSAaron Conole ): 1183e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1184e52b07aaSAaron Conole self, 1185e52b07aaSAaron Conole "ct_tuple4", 1186e52b07aaSAaron Conole data=data, 1187e52b07aaSAaron Conole offset=offset, 1188e52b07aaSAaron Conole parent=parent, 1189e52b07aaSAaron Conole length=length, 1190e52b07aaSAaron Conole init=init, 1191e52b07aaSAaron Conole ) 1192e52b07aaSAaron Conole 1193e52b07aaSAaron Conole class ovs_key_ct_tuple_ipv6(nla): 1194e52b07aaSAaron Conole fields = ( 1195e52b07aaSAaron Conole ("src", "!16s"), 1196e52b07aaSAaron Conole ("dst", "!16s"), 1197e52b07aaSAaron Conole ("tp_src", "!H"), 1198e52b07aaSAaron Conole ("tp_dst", "!H"), 1199e52b07aaSAaron Conole ("proto", "B"), 1200e52b07aaSAaron Conole ) 1201e52b07aaSAaron Conole 1202e52b07aaSAaron Conole fields_map = ( 1203e52b07aaSAaron Conole ( 1204e52b07aaSAaron Conole "src", 1205e52b07aaSAaron Conole "src", 1206e52b07aaSAaron Conole lambda x: str(ipaddress.IPv6Address(x)), 1207e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big", convertmac), 1208e52b07aaSAaron Conole ), 1209e52b07aaSAaron Conole ( 1210e52b07aaSAaron Conole "dst", 1211e52b07aaSAaron Conole "dst", 1212e52b07aaSAaron Conole lambda x: str(ipaddress.IPv6Address(x)), 1213e52b07aaSAaron Conole lambda x: int.from_bytes(x, "big"), 1214e52b07aaSAaron Conole ), 1215e52b07aaSAaron Conole ("tp_src", "tp_src", "%d", int), 1216e52b07aaSAaron Conole ("tp_dst", "tp_dst", "%d", int), 1217e52b07aaSAaron Conole ("proto", "proto", "%d", int), 1218e52b07aaSAaron Conole ) 1219e52b07aaSAaron Conole 1220e52b07aaSAaron Conole def __init__( 1221e52b07aaSAaron Conole self, 1222e52b07aaSAaron Conole data=None, 1223e52b07aaSAaron Conole offset=None, 1224e52b07aaSAaron Conole parent=None, 1225e52b07aaSAaron Conole length=None, 1226e52b07aaSAaron Conole init=None, 1227e52b07aaSAaron Conole ): 1228e52b07aaSAaron Conole ovskey.ovs_key_proto.__init__( 1229e52b07aaSAaron Conole self, 1230e52b07aaSAaron Conole "ct_tuple6", 1231e52b07aaSAaron Conole data=data, 1232e52b07aaSAaron Conole offset=offset, 1233e52b07aaSAaron Conole parent=parent, 1234e52b07aaSAaron Conole length=length, 1235e52b07aaSAaron Conole init=init, 1236e52b07aaSAaron Conole ) 1237e52b07aaSAaron Conole 1238e52b07aaSAaron Conole class ovs_key_mpls(nla): 1239e52b07aaSAaron Conole fields = (("lse", ">I"),) 1240e52b07aaSAaron Conole 1241918423fdSAaron Conole def parse(self, flowstr, mask=None): 1242918423fdSAaron Conole for field in ( 1243918423fdSAaron Conole ("OVS_KEY_ATTR_PRIORITY", "skb_priority", intparse), 1244918423fdSAaron Conole ("OVS_KEY_ATTR_SKB_MARK", "skb_mark", intparse), 1245918423fdSAaron Conole ("OVS_KEY_ATTR_RECIRC_ID", "recirc_id", intparse), 1246918423fdSAaron Conole ("OVS_KEY_ATTR_DP_HASH", "dp_hash", intparse), 1247918423fdSAaron Conole ("OVS_KEY_ATTR_CT_STATE", "ct_state", parse_ct_state), 1248918423fdSAaron Conole ("OVS_KEY_ATTR_CT_ZONE", "ct_zone", intparse), 1249918423fdSAaron Conole ("OVS_KEY_ATTR_CT_MARK", "ct_mark", intparse), 1250918423fdSAaron Conole ("OVS_KEY_ATTR_IN_PORT", "in_port", intparse), 1251918423fdSAaron Conole ( 1252918423fdSAaron Conole "OVS_KEY_ATTR_ETHERNET", 1253918423fdSAaron Conole "eth", 1254918423fdSAaron Conole ovskey.ethaddr, 1255918423fdSAaron Conole ), 1256918423fdSAaron Conole ( 1257918423fdSAaron Conole "OVS_KEY_ATTR_ETHERTYPE", 1258918423fdSAaron Conole "eth_type", 1259918423fdSAaron Conole lambda x: intparse(x, "0xffff"), 1260918423fdSAaron Conole ), 1261918423fdSAaron Conole ( 1262918423fdSAaron Conole "OVS_KEY_ATTR_IPV4", 1263918423fdSAaron Conole "ipv4", 1264918423fdSAaron Conole ovskey.ovs_key_ipv4, 1265918423fdSAaron Conole ), 1266918423fdSAaron Conole ( 1267918423fdSAaron Conole "OVS_KEY_ATTR_IPV6", 1268918423fdSAaron Conole "ipv6", 1269918423fdSAaron Conole ovskey.ovs_key_ipv6, 1270918423fdSAaron Conole ), 1271918423fdSAaron Conole ( 1272918423fdSAaron Conole "OVS_KEY_ATTR_ARP", 1273918423fdSAaron Conole "arp", 1274918423fdSAaron Conole ovskey.ovs_key_arp, 1275918423fdSAaron Conole ), 1276918423fdSAaron Conole ( 1277918423fdSAaron Conole "OVS_KEY_ATTR_TCP", 1278918423fdSAaron Conole "tcp", 1279918423fdSAaron Conole ovskey.ovs_key_tcp, 1280918423fdSAaron Conole ), 1281918423fdSAaron Conole ( 12829f1179fbSAdrian Moreno "OVS_KEY_ATTR_UDP", 12839f1179fbSAdrian Moreno "udp", 12849f1179fbSAdrian Moreno ovskey.ovs_key_udp, 12859f1179fbSAdrian Moreno ), 12869f1179fbSAdrian Moreno ( 12879f1179fbSAdrian Moreno "OVS_KEY_ATTR_ICMP", 12889f1179fbSAdrian Moreno "icmp", 12899f1179fbSAdrian Moreno ovskey.ovs_key_icmp, 12909f1179fbSAdrian Moreno ), 12919f1179fbSAdrian Moreno ( 1292918423fdSAaron Conole "OVS_KEY_ATTR_TCP_FLAGS", 1293918423fdSAaron Conole "tcp_flags", 1294918423fdSAaron Conole lambda x: parse_flags(x, None), 1295918423fdSAaron Conole ), 1296918423fdSAaron Conole ): 1297918423fdSAaron Conole fld = field[1] + "(" 1298918423fdSAaron Conole if not flowstr.startswith(fld): 1299918423fdSAaron Conole continue 1300918423fdSAaron Conole 1301918423fdSAaron Conole if not isinstance(field[2], types.FunctionType): 1302918423fdSAaron Conole nk = field[2]() 1303918423fdSAaron Conole flowstr, k, m = nk.parse(flowstr, field[2]) 1304918423fdSAaron Conole else: 1305918423fdSAaron Conole flowstr = flowstr[len(fld) :] 1306918423fdSAaron Conole flowstr, k, m = field[2](flowstr) 1307918423fdSAaron Conole 1308918423fdSAaron Conole if m and mask is not None: 1309918423fdSAaron Conole mask["attrs"].append([field[0], m]) 1310918423fdSAaron Conole self["attrs"].append([field[0], k]) 1311918423fdSAaron Conole 1312918423fdSAaron Conole flowstr = flowstr[strspn(flowstr, "),") :] 1313918423fdSAaron Conole 1314918423fdSAaron Conole return flowstr 1315918423fdSAaron Conole 1316e52b07aaSAaron Conole def dpstr(self, mask=None, more=False): 1317e52b07aaSAaron Conole print_str = "" 1318e52b07aaSAaron Conole 1319e52b07aaSAaron Conole for field in ( 1320e52b07aaSAaron Conole ( 1321e52b07aaSAaron Conole "OVS_KEY_ATTR_PRIORITY", 1322e52b07aaSAaron Conole "skb_priority", 1323e52b07aaSAaron Conole "%d", 1324e52b07aaSAaron Conole lambda x: False, 1325e52b07aaSAaron Conole True, 1326e52b07aaSAaron Conole ), 1327e52b07aaSAaron Conole ( 1328e52b07aaSAaron Conole "OVS_KEY_ATTR_SKB_MARK", 1329e52b07aaSAaron Conole "skb_mark", 1330e52b07aaSAaron Conole "%d", 1331e52b07aaSAaron Conole lambda x: False, 1332e52b07aaSAaron Conole True, 1333e52b07aaSAaron Conole ), 1334e52b07aaSAaron Conole ( 1335e52b07aaSAaron Conole "OVS_KEY_ATTR_RECIRC_ID", 1336e52b07aaSAaron Conole "recirc_id", 1337e52b07aaSAaron Conole "0x%08X", 1338e52b07aaSAaron Conole lambda x: False, 1339e52b07aaSAaron Conole True, 1340e52b07aaSAaron Conole ), 1341e52b07aaSAaron Conole ( 1342e52b07aaSAaron Conole "OVS_KEY_ATTR_DP_HASH", 1343e52b07aaSAaron Conole "dp_hash", 1344e52b07aaSAaron Conole "0x%08X", 1345e52b07aaSAaron Conole lambda x: False, 1346e52b07aaSAaron Conole True, 1347e52b07aaSAaron Conole ), 1348e52b07aaSAaron Conole ( 1349e52b07aaSAaron Conole "OVS_KEY_ATTR_CT_STATE", 1350e52b07aaSAaron Conole "ct_state", 1351e52b07aaSAaron Conole "0x%04x", 1352e52b07aaSAaron Conole lambda x: False, 1353e52b07aaSAaron Conole True, 1354e52b07aaSAaron Conole ), 1355e52b07aaSAaron Conole ( 1356e52b07aaSAaron Conole "OVS_KEY_ATTR_CT_ZONE", 1357e52b07aaSAaron Conole "ct_zone", 1358e52b07aaSAaron Conole "0x%04x", 1359e52b07aaSAaron Conole lambda x: False, 1360e52b07aaSAaron Conole True, 1361e52b07aaSAaron Conole ), 1362e52b07aaSAaron Conole ( 1363e52b07aaSAaron Conole "OVS_KEY_ATTR_CT_MARK", 1364e52b07aaSAaron Conole "ct_mark", 1365e52b07aaSAaron Conole "0x%08x", 1366e52b07aaSAaron Conole lambda x: False, 1367e52b07aaSAaron Conole True, 1368e52b07aaSAaron Conole ), 1369e52b07aaSAaron Conole ( 1370e52b07aaSAaron Conole "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4", 1371e52b07aaSAaron Conole None, 1372e52b07aaSAaron Conole None, 1373e52b07aaSAaron Conole False, 1374e52b07aaSAaron Conole False, 1375e52b07aaSAaron Conole ), 1376e52b07aaSAaron Conole ( 1377e52b07aaSAaron Conole "OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6", 1378e52b07aaSAaron Conole None, 1379e52b07aaSAaron Conole None, 1380e52b07aaSAaron Conole False, 1381e52b07aaSAaron Conole False, 1382e52b07aaSAaron Conole ), 1383e52b07aaSAaron Conole ( 1384e52b07aaSAaron Conole "OVS_KEY_ATTR_IN_PORT", 1385e52b07aaSAaron Conole "in_port", 1386e52b07aaSAaron Conole "%d", 1387e52b07aaSAaron Conole lambda x: True, 1388e52b07aaSAaron Conole True, 1389e52b07aaSAaron Conole ), 1390e52b07aaSAaron Conole ("OVS_KEY_ATTR_ETHERNET", None, None, False, False), 1391e52b07aaSAaron Conole ( 1392e52b07aaSAaron Conole "OVS_KEY_ATTR_ETHERTYPE", 1393e52b07aaSAaron Conole "eth_type", 1394e52b07aaSAaron Conole "0x%04x", 1395e52b07aaSAaron Conole lambda x: int(x) == 0xFFFF, 1396e52b07aaSAaron Conole True, 1397e52b07aaSAaron Conole ), 1398e52b07aaSAaron Conole ("OVS_KEY_ATTR_IPV4", None, None, False, False), 1399e52b07aaSAaron Conole ("OVS_KEY_ATTR_IPV6", None, None, False, False), 1400e52b07aaSAaron Conole ("OVS_KEY_ATTR_ARP", None, None, False, False), 1401e52b07aaSAaron Conole ("OVS_KEY_ATTR_TCP", None, None, False, False), 1402e52b07aaSAaron Conole ( 1403e52b07aaSAaron Conole "OVS_KEY_ATTR_TCP_FLAGS", 1404e52b07aaSAaron Conole "tcp_flags", 1405e52b07aaSAaron Conole "0x%04x", 1406e52b07aaSAaron Conole lambda x: False, 1407e52b07aaSAaron Conole True, 1408e52b07aaSAaron Conole ), 1409e52b07aaSAaron Conole ("OVS_KEY_ATTR_UDP", None, None, False, False), 1410e52b07aaSAaron Conole ("OVS_KEY_ATTR_SCTP", None, None, False, False), 1411e52b07aaSAaron Conole ("OVS_KEY_ATTR_ICMP", None, None, False, False), 1412e52b07aaSAaron Conole ("OVS_KEY_ATTR_ICMPV6", None, None, False, False), 1413e52b07aaSAaron Conole ("OVS_KEY_ATTR_ND", None, None, False, False), 1414e52b07aaSAaron Conole ): 1415e52b07aaSAaron Conole v = self.get_attr(field[0]) 1416e52b07aaSAaron Conole if v is not None: 1417e52b07aaSAaron Conole m = None if mask is None else mask.get_attr(field[0]) 1418e52b07aaSAaron Conole if field[4] is False: 1419e52b07aaSAaron Conole print_str += v.dpstr(m, more) 1420e52b07aaSAaron Conole print_str += "," 1421e52b07aaSAaron Conole else: 1422e52b07aaSAaron Conole if m is None or field[3](m): 1423e52b07aaSAaron Conole print_str += field[1] + "(" 1424e52b07aaSAaron Conole print_str += field[2] % v 1425e52b07aaSAaron Conole print_str += ")," 1426e52b07aaSAaron Conole elif more or m != 0: 1427e52b07aaSAaron Conole print_str += field[1] + "(" 1428e52b07aaSAaron Conole print_str += (field[2] % v) + "/" + (field[2] % m) 1429e52b07aaSAaron Conole print_str += ")," 1430e52b07aaSAaron Conole 1431e52b07aaSAaron Conole return print_str 1432e52b07aaSAaron Conole 1433e52b07aaSAaron Conole 14349feac87bSAaron Conoleclass OvsPacket(GenericNetlinkSocket): 14359feac87bSAaron Conole OVS_PACKET_CMD_MISS = 1 # Flow table miss 14369feac87bSAaron Conole OVS_PACKET_CMD_ACTION = 2 # USERSPACE action 14379feac87bSAaron Conole OVS_PACKET_CMD_EXECUTE = 3 # Apply actions to packet 14389feac87bSAaron Conole 14399feac87bSAaron Conole class ovs_packet_msg(ovs_dp_msg): 14409feac87bSAaron Conole nla_map = ( 14419feac87bSAaron Conole ("OVS_PACKET_ATTR_UNSPEC", "none"), 14429feac87bSAaron Conole ("OVS_PACKET_ATTR_PACKET", "array(uint8)"), 14439feac87bSAaron Conole ("OVS_PACKET_ATTR_KEY", "ovskey"), 14449feac87bSAaron Conole ("OVS_PACKET_ATTR_ACTIONS", "ovsactions"), 14459feac87bSAaron Conole ("OVS_PACKET_ATTR_USERDATA", "none"), 14469feac87bSAaron Conole ("OVS_PACKET_ATTR_EGRESS_TUN_KEY", "none"), 14479feac87bSAaron Conole ("OVS_PACKET_ATTR_UNUSED1", "none"), 14489feac87bSAaron Conole ("OVS_PACKET_ATTR_UNUSED2", "none"), 14499feac87bSAaron Conole ("OVS_PACKET_ATTR_PROBE", "none"), 14509feac87bSAaron Conole ("OVS_PACKET_ATTR_MRU", "uint16"), 14519feac87bSAaron Conole ("OVS_PACKET_ATTR_LEN", "uint32"), 14529feac87bSAaron Conole ("OVS_PACKET_ATTR_HASH", "uint64"), 14539feac87bSAaron Conole ) 14549feac87bSAaron Conole 14559feac87bSAaron Conole def __init__(self): 14569feac87bSAaron Conole GenericNetlinkSocket.__init__(self) 14579feac87bSAaron Conole self.bind(OVS_PACKET_FAMILY, OvsPacket.ovs_packet_msg) 14589feac87bSAaron Conole 14599feac87bSAaron Conole def upcall_handler(self, up=None): 14609feac87bSAaron Conole print("listening on upcall packet handler:", self.epid) 14619feac87bSAaron Conole while True: 14629feac87bSAaron Conole try: 14639feac87bSAaron Conole msgs = self.get() 14649feac87bSAaron Conole for msg in msgs: 14659feac87bSAaron Conole if not up: 14669feac87bSAaron Conole continue 14679feac87bSAaron Conole if msg["cmd"] == OvsPacket.OVS_PACKET_CMD_MISS: 14689feac87bSAaron Conole up.miss(msg) 14699feac87bSAaron Conole elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_ACTION: 14709feac87bSAaron Conole up.action(msg) 14719feac87bSAaron Conole elif msg["cmd"] == OvsPacket.OVS_PACKET_CMD_EXECUTE: 14729feac87bSAaron Conole up.execute(msg) 14739feac87bSAaron Conole else: 14749feac87bSAaron Conole print("Unkonwn cmd: %d" % msg["cmd"]) 14759feac87bSAaron Conole except NetlinkError as ne: 14769feac87bSAaron Conole raise ne 14779feac87bSAaron Conole 14789feac87bSAaron Conole 147925f16c87SAaron Conoleclass OvsDatapath(GenericNetlinkSocket): 148025f16c87SAaron Conole OVS_DP_F_VPORT_PIDS = 1 << 1 148125f16c87SAaron Conole OVS_DP_F_DISPATCH_UPCALL_PER_CPU = 1 << 3 148225f16c87SAaron Conole 148325f16c87SAaron Conole class dp_cmd_msg(ovs_dp_msg): 148425f16c87SAaron Conole """ 148525f16c87SAaron Conole Message class that will be used to communicate with the kernel module. 148625f16c87SAaron Conole """ 148725f16c87SAaron Conole 148825f16c87SAaron Conole nla_map = ( 148925f16c87SAaron Conole ("OVS_DP_ATTR_UNSPEC", "none"), 149025f16c87SAaron Conole ("OVS_DP_ATTR_NAME", "asciiz"), 1491306dc213SAaron Conole ("OVS_DP_ATTR_UPCALL_PID", "array(uint32)"), 149225f16c87SAaron Conole ("OVS_DP_ATTR_STATS", "dpstats"), 149325f16c87SAaron Conole ("OVS_DP_ATTR_MEGAFLOW_STATS", "megaflowstats"), 149425f16c87SAaron Conole ("OVS_DP_ATTR_USER_FEATURES", "uint32"), 149525f16c87SAaron Conole ("OVS_DP_ATTR_PAD", "none"), 149625f16c87SAaron Conole ("OVS_DP_ATTR_MASKS_CACHE_SIZE", "uint32"), 149725f16c87SAaron Conole ("OVS_DP_ATTR_PER_CPU_PIDS", "array(uint32)"), 149825f16c87SAaron Conole ) 149925f16c87SAaron Conole 150025f16c87SAaron Conole class dpstats(nla): 150125f16c87SAaron Conole fields = ( 150225f16c87SAaron Conole ("hit", "=Q"), 150325f16c87SAaron Conole ("missed", "=Q"), 150425f16c87SAaron Conole ("lost", "=Q"), 150525f16c87SAaron Conole ("flows", "=Q"), 150625f16c87SAaron Conole ) 150725f16c87SAaron Conole 150825f16c87SAaron Conole class megaflowstats(nla): 150925f16c87SAaron Conole fields = ( 151025f16c87SAaron Conole ("mask_hit", "=Q"), 151125f16c87SAaron Conole ("masks", "=I"), 151225f16c87SAaron Conole ("padding", "=I"), 151325f16c87SAaron Conole ("cache_hits", "=Q"), 151425f16c87SAaron Conole ("pad1", "=Q"), 151525f16c87SAaron Conole ) 151625f16c87SAaron Conole 151725f16c87SAaron Conole def __init__(self): 151825f16c87SAaron Conole GenericNetlinkSocket.__init__(self) 151925f16c87SAaron Conole self.bind(OVS_DATAPATH_FAMILY, OvsDatapath.dp_cmd_msg) 152025f16c87SAaron Conole 152125f16c87SAaron Conole def info(self, dpname, ifindex=0): 152225f16c87SAaron Conole msg = OvsDatapath.dp_cmd_msg() 152325f16c87SAaron Conole msg["cmd"] = OVS_DP_CMD_GET 152425f16c87SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 152525f16c87SAaron Conole msg["reserved"] = 0 152625f16c87SAaron Conole msg["dpifindex"] = ifindex 152725f16c87SAaron Conole msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 152825f16c87SAaron Conole 152925f16c87SAaron Conole try: 153025f16c87SAaron Conole reply = self.nlm_request( 153125f16c87SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST 153225f16c87SAaron Conole ) 153325f16c87SAaron Conole reply = reply[0] 153425f16c87SAaron Conole except NetlinkError as ne: 153525f16c87SAaron Conole if ne.code == errno.ENODEV: 153625f16c87SAaron Conole reply = None 153725f16c87SAaron Conole else: 153825f16c87SAaron Conole raise ne 153925f16c87SAaron Conole 154025f16c87SAaron Conole return reply 154125f16c87SAaron Conole 15429feac87bSAaron Conole def create( 15439feac87bSAaron Conole self, dpname, shouldUpcall=False, versionStr=None, p=OvsPacket() 15449feac87bSAaron Conole ): 154525f16c87SAaron Conole msg = OvsDatapath.dp_cmd_msg() 154625f16c87SAaron Conole msg["cmd"] = OVS_DP_CMD_NEW 154725f16c87SAaron Conole if versionStr is None: 154825f16c87SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 154925f16c87SAaron Conole else: 155025f16c87SAaron Conole msg["version"] = int(versionStr.split(":")[0], 0) 155125f16c87SAaron Conole msg["reserved"] = 0 155225f16c87SAaron Conole msg["dpifindex"] = 0 155325f16c87SAaron Conole msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 155425f16c87SAaron Conole 155525f16c87SAaron Conole dpfeatures = 0 155625f16c87SAaron Conole if versionStr is not None and versionStr.find(":") != -1: 155725f16c87SAaron Conole dpfeatures = int(versionStr.split(":")[1], 0) 155825f16c87SAaron Conole else: 15599feac87bSAaron Conole if versionStr is None or versionStr.find(":") == -1: 15609feac87bSAaron Conole dpfeatures |= OvsDatapath.OVS_DP_F_DISPATCH_UPCALL_PER_CPU 15619feac87bSAaron Conole dpfeatures &= ~OvsDatapath.OVS_DP_F_VPORT_PIDS 156225f16c87SAaron Conole 15639feac87bSAaron Conole nproc = multiprocessing.cpu_count() 15649feac87bSAaron Conole procarray = [] 15659feac87bSAaron Conole for i in range(1, nproc): 15669feac87bSAaron Conole procarray += [int(p.epid)] 15679feac87bSAaron Conole msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", procarray]) 156825f16c87SAaron Conole msg["attrs"].append(["OVS_DP_ATTR_USER_FEATURES", dpfeatures]) 156925f16c87SAaron Conole if not shouldUpcall: 15709feac87bSAaron Conole msg["attrs"].append(["OVS_DP_ATTR_UPCALL_PID", [0]]) 157125f16c87SAaron Conole 157225f16c87SAaron Conole try: 157325f16c87SAaron Conole reply = self.nlm_request( 157425f16c87SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 157525f16c87SAaron Conole ) 157625f16c87SAaron Conole reply = reply[0] 157725f16c87SAaron Conole except NetlinkError as ne: 157825f16c87SAaron Conole if ne.code == errno.EEXIST: 157925f16c87SAaron Conole reply = None 158025f16c87SAaron Conole else: 158125f16c87SAaron Conole raise ne 158225f16c87SAaron Conole 158325f16c87SAaron Conole return reply 158425f16c87SAaron Conole 158525f16c87SAaron Conole def destroy(self, dpname): 158625f16c87SAaron Conole msg = OvsDatapath.dp_cmd_msg() 158725f16c87SAaron Conole msg["cmd"] = OVS_DP_CMD_DEL 158825f16c87SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 158925f16c87SAaron Conole msg["reserved"] = 0 159025f16c87SAaron Conole msg["dpifindex"] = 0 159125f16c87SAaron Conole msg["attrs"].append(["OVS_DP_ATTR_NAME", dpname]) 159225f16c87SAaron Conole 159325f16c87SAaron Conole try: 159425f16c87SAaron Conole reply = self.nlm_request( 159525f16c87SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 159625f16c87SAaron Conole ) 159725f16c87SAaron Conole reply = reply[0] 159825f16c87SAaron Conole except NetlinkError as ne: 159925f16c87SAaron Conole if ne.code == errno.ENODEV: 160025f16c87SAaron Conole reply = None 160125f16c87SAaron Conole else: 160225f16c87SAaron Conole raise ne 160325f16c87SAaron Conole 160425f16c87SAaron Conole return reply 160525f16c87SAaron Conole 160625f16c87SAaron Conole 160725f16c87SAaron Conoleclass OvsVport(GenericNetlinkSocket): 160874cc26f4SAaron Conole OVS_VPORT_TYPE_NETDEV = 1 160974cc26f4SAaron Conole OVS_VPORT_TYPE_INTERNAL = 2 161074cc26f4SAaron Conole OVS_VPORT_TYPE_GRE = 3 161174cc26f4SAaron Conole OVS_VPORT_TYPE_VXLAN = 4 161274cc26f4SAaron Conole OVS_VPORT_TYPE_GENEVE = 5 161374cc26f4SAaron Conole 161425f16c87SAaron Conole class ovs_vport_msg(ovs_dp_msg): 161525f16c87SAaron Conole nla_map = ( 161625f16c87SAaron Conole ("OVS_VPORT_ATTR_UNSPEC", "none"), 161725f16c87SAaron Conole ("OVS_VPORT_ATTR_PORT_NO", "uint32"), 161825f16c87SAaron Conole ("OVS_VPORT_ATTR_TYPE", "uint32"), 161925f16c87SAaron Conole ("OVS_VPORT_ATTR_NAME", "asciiz"), 162025f16c87SAaron Conole ("OVS_VPORT_ATTR_OPTIONS", "none"), 162125f16c87SAaron Conole ("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"), 162225f16c87SAaron Conole ("OVS_VPORT_ATTR_STATS", "vportstats"), 162325f16c87SAaron Conole ("OVS_VPORT_ATTR_PAD", "none"), 162425f16c87SAaron Conole ("OVS_VPORT_ATTR_IFINDEX", "uint32"), 162525f16c87SAaron Conole ("OVS_VPORT_ATTR_NETNSID", "uint32"), 162625f16c87SAaron Conole ) 162725f16c87SAaron Conole 162825f16c87SAaron Conole class vportstats(nla): 162925f16c87SAaron Conole fields = ( 163025f16c87SAaron Conole ("rx_packets", "=Q"), 163125f16c87SAaron Conole ("tx_packets", "=Q"), 163225f16c87SAaron Conole ("rx_bytes", "=Q"), 163325f16c87SAaron Conole ("tx_bytes", "=Q"), 163425f16c87SAaron Conole ("rx_errors", "=Q"), 163525f16c87SAaron Conole ("tx_errors", "=Q"), 163625f16c87SAaron Conole ("rx_dropped", "=Q"), 163725f16c87SAaron Conole ("tx_dropped", "=Q"), 163825f16c87SAaron Conole ) 163925f16c87SAaron Conole 164025f16c87SAaron Conole def type_to_str(vport_type): 164174cc26f4SAaron Conole if vport_type == OvsVport.OVS_VPORT_TYPE_NETDEV: 164225f16c87SAaron Conole return "netdev" 164374cc26f4SAaron Conole elif vport_type == OvsVport.OVS_VPORT_TYPE_INTERNAL: 164425f16c87SAaron Conole return "internal" 164574cc26f4SAaron Conole elif vport_type == OvsVport.OVS_VPORT_TYPE_GRE: 164625f16c87SAaron Conole return "gre" 164774cc26f4SAaron Conole elif vport_type == OvsVport.OVS_VPORT_TYPE_VXLAN: 164825f16c87SAaron Conole return "vxlan" 164974cc26f4SAaron Conole elif vport_type == OvsVport.OVS_VPORT_TYPE_GENEVE: 165025f16c87SAaron Conole return "geneve" 165174cc26f4SAaron Conole raise ValueError("Unknown vport type:%d" % vport_type) 165274cc26f4SAaron Conole 165374cc26f4SAaron Conole def str_to_type(vport_type): 165474cc26f4SAaron Conole if vport_type == "netdev": 165574cc26f4SAaron Conole return OvsVport.OVS_VPORT_TYPE_NETDEV 165674cc26f4SAaron Conole elif vport_type == "internal": 165774cc26f4SAaron Conole return OvsVport.OVS_VPORT_TYPE_INTERNAL 165874cc26f4SAaron Conole elif vport_type == "gre": 165974cc26f4SAaron Conole return OvsVport.OVS_VPORT_TYPE_INTERNAL 166074cc26f4SAaron Conole elif vport_type == "vxlan": 166174cc26f4SAaron Conole return OvsVport.OVS_VPORT_TYPE_VXLAN 166274cc26f4SAaron Conole elif vport_type == "geneve": 166374cc26f4SAaron Conole return OvsVport.OVS_VPORT_TYPE_GENEVE 166474cc26f4SAaron Conole raise ValueError("Unknown vport type: '%s'" % vport_type) 166525f16c87SAaron Conole 16669feac87bSAaron Conole def __init__(self, packet=OvsPacket()): 166725f16c87SAaron Conole GenericNetlinkSocket.__init__(self) 166825f16c87SAaron Conole self.bind(OVS_VPORT_FAMILY, OvsVport.ovs_vport_msg) 16699feac87bSAaron Conole self.upcall_packet = packet 167025f16c87SAaron Conole 167125f16c87SAaron Conole def info(self, vport_name, dpifindex=0, portno=None): 167225f16c87SAaron Conole msg = OvsVport.ovs_vport_msg() 167325f16c87SAaron Conole 167425f16c87SAaron Conole msg["cmd"] = OVS_VPORT_CMD_GET 167525f16c87SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 167625f16c87SAaron Conole msg["reserved"] = 0 167725f16c87SAaron Conole msg["dpifindex"] = dpifindex 167825f16c87SAaron Conole 167925f16c87SAaron Conole if portno is None: 168025f16c87SAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_name]) 168125f16c87SAaron Conole else: 168225f16c87SAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_PORT_NO", portno]) 168325f16c87SAaron Conole 168425f16c87SAaron Conole try: 168525f16c87SAaron Conole reply = self.nlm_request( 168625f16c87SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST 168725f16c87SAaron Conole ) 168825f16c87SAaron Conole reply = reply[0] 168925f16c87SAaron Conole except NetlinkError as ne: 169025f16c87SAaron Conole if ne.code == errno.ENODEV: 169125f16c87SAaron Conole reply = None 169225f16c87SAaron Conole else: 169325f16c87SAaron Conole raise ne 169425f16c87SAaron Conole return reply 169525f16c87SAaron Conole 169674cc26f4SAaron Conole def attach(self, dpindex, vport_ifname, ptype): 169774cc26f4SAaron Conole msg = OvsVport.ovs_vport_msg() 169825f16c87SAaron Conole 169974cc26f4SAaron Conole msg["cmd"] = OVS_VPORT_CMD_NEW 170074cc26f4SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 170174cc26f4SAaron Conole msg["reserved"] = 0 170274cc26f4SAaron Conole msg["dpifindex"] = dpindex 170374cc26f4SAaron Conole port_type = OvsVport.str_to_type(ptype) 170474cc26f4SAaron Conole 170574cc26f4SAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type]) 170674cc26f4SAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 17079feac87bSAaron Conole msg["attrs"].append( 17089feac87bSAaron Conole ["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]] 17099feac87bSAaron Conole ) 17109feac87bSAaron Conole 17119feac87bSAaron Conole try: 17129feac87bSAaron Conole reply = self.nlm_request( 17139feac87bSAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 17149feac87bSAaron Conole ) 17159feac87bSAaron Conole reply = reply[0] 17169feac87bSAaron Conole except NetlinkError as ne: 17179feac87bSAaron Conole if ne.code == errno.EEXIST: 17189feac87bSAaron Conole reply = None 17199feac87bSAaron Conole else: 17209feac87bSAaron Conole raise ne 17219feac87bSAaron Conole return reply 17229feac87bSAaron Conole 17239feac87bSAaron Conole def reset_upcall(self, dpindex, vport_ifname, p=None): 17249feac87bSAaron Conole msg = OvsVport.ovs_vport_msg() 17259feac87bSAaron Conole 17269feac87bSAaron Conole msg["cmd"] = OVS_VPORT_CMD_SET 17279feac87bSAaron Conole msg["version"] = OVS_DATAPATH_VERSION 17289feac87bSAaron Conole msg["reserved"] = 0 17299feac87bSAaron Conole msg["dpifindex"] = dpindex 17309feac87bSAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 17319feac87bSAaron Conole 17329feac87bSAaron Conole if p == None: 17339feac87bSAaron Conole p = self.upcall_packet 17349feac87bSAaron Conole else: 17359feac87bSAaron Conole self.upcall_packet = p 17369feac87bSAaron Conole 17379feac87bSAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_UPCALL_PID", [p.epid]]) 173874cc26f4SAaron Conole 173974cc26f4SAaron Conole try: 174074cc26f4SAaron Conole reply = self.nlm_request( 174174cc26f4SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 174274cc26f4SAaron Conole ) 174374cc26f4SAaron Conole reply = reply[0] 174474cc26f4SAaron Conole except NetlinkError as ne: 174574cc26f4SAaron Conole raise ne 174674cc26f4SAaron Conole return reply 174774cc26f4SAaron Conole 174874cc26f4SAaron Conole def detach(self, dpindex, vport_ifname): 174974cc26f4SAaron Conole msg = OvsVport.ovs_vport_msg() 175074cc26f4SAaron Conole 175174cc26f4SAaron Conole msg["cmd"] = OVS_VPORT_CMD_DEL 175274cc26f4SAaron Conole msg["version"] = OVS_DATAPATH_VERSION 175374cc26f4SAaron Conole msg["reserved"] = 0 175474cc26f4SAaron Conole msg["dpifindex"] = dpindex 175574cc26f4SAaron Conole msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) 175674cc26f4SAaron Conole 175774cc26f4SAaron Conole try: 175874cc26f4SAaron Conole reply = self.nlm_request( 175974cc26f4SAaron Conole msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK 176074cc26f4SAaron Conole ) 176174cc26f4SAaron Conole reply = reply[0] 176274cc26f4SAaron Conole except NetlinkError as ne: 176374cc26f4SAaron Conole if ne.code == errno.ENODEV: 176474cc26f4SAaron Conole reply = None 176574cc26f4SAaron Conole else: 176674cc26f4SAaron Conole raise ne 176774cc26f4SAaron Conole return reply 176874cc26f4SAaron Conole 17699feac87bSAaron Conole def upcall_handler(self, handler=None): 17709feac87bSAaron Conole self.upcall_packet.upcall_handler(handler) 17719feac87bSAaron Conole 177274cc26f4SAaron Conole 1773e52b07aaSAaron Conoleclass OvsFlow(GenericNetlinkSocket): 1774e52b07aaSAaron Conole class ovs_flow_msg(ovs_dp_msg): 1775e52b07aaSAaron Conole nla_map = ( 1776e52b07aaSAaron Conole ("OVS_FLOW_ATTR_UNSPEC", "none"), 1777e52b07aaSAaron Conole ("OVS_FLOW_ATTR_KEY", "ovskey"), 1778e52b07aaSAaron Conole ("OVS_FLOW_ATTR_ACTIONS", "ovsactions"), 1779e52b07aaSAaron Conole ("OVS_FLOW_ATTR_STATS", "flowstats"), 1780e52b07aaSAaron Conole ("OVS_FLOW_ATTR_TCP_FLAGS", "uint8"), 1781e52b07aaSAaron Conole ("OVS_FLOW_ATTR_USED", "uint64"), 1782e52b07aaSAaron Conole ("OVS_FLOW_ATTR_CLEAR", "none"), 1783e52b07aaSAaron Conole ("OVS_FLOW_ATTR_MASK", "ovskey"), 1784e52b07aaSAaron Conole ("OVS_FLOW_ATTR_PROBE", "none"), 1785e52b07aaSAaron Conole ("OVS_FLOW_ATTR_UFID", "array(uint32)"), 1786e52b07aaSAaron Conole ("OVS_FLOW_ATTR_UFID_FLAGS", "uint32"), 1787e52b07aaSAaron Conole ) 1788e52b07aaSAaron Conole 1789e52b07aaSAaron Conole class flowstats(nla): 1790e52b07aaSAaron Conole fields = ( 1791e52b07aaSAaron Conole ("packets", "=Q"), 1792e52b07aaSAaron Conole ("bytes", "=Q"), 1793e52b07aaSAaron Conole ) 1794e52b07aaSAaron Conole 1795e52b07aaSAaron Conole def dpstr(self, more=False): 1796e52b07aaSAaron Conole ufid = self.get_attr("OVS_FLOW_ATTR_UFID") 1797e52b07aaSAaron Conole ufid_str = "" 1798e52b07aaSAaron Conole if ufid is not None: 1799e52b07aaSAaron Conole ufid_str = ( 1800e52b07aaSAaron Conole "ufid:{:08x}-{:04x}-{:04x}-{:04x}-{:04x}{:08x}".format( 1801e52b07aaSAaron Conole ufid[0], 1802e52b07aaSAaron Conole ufid[1] >> 16, 1803e52b07aaSAaron Conole ufid[1] & 0xFFFF, 1804e52b07aaSAaron Conole ufid[2] >> 16, 1805e52b07aaSAaron Conole ufid[2] & 0, 1806e52b07aaSAaron Conole ufid[3], 1807e52b07aaSAaron Conole ) 1808e52b07aaSAaron Conole ) 1809e52b07aaSAaron Conole 1810e52b07aaSAaron Conole key_field = self.get_attr("OVS_FLOW_ATTR_KEY") 1811e52b07aaSAaron Conole keymsg = None 1812e52b07aaSAaron Conole if key_field is not None: 1813e52b07aaSAaron Conole keymsg = key_field 1814e52b07aaSAaron Conole 1815e52b07aaSAaron Conole mask_field = self.get_attr("OVS_FLOW_ATTR_MASK") 1816e52b07aaSAaron Conole maskmsg = None 1817e52b07aaSAaron Conole if mask_field is not None: 1818e52b07aaSAaron Conole maskmsg = mask_field 1819e52b07aaSAaron Conole 1820e52b07aaSAaron Conole acts_field = self.get_attr("OVS_FLOW_ATTR_ACTIONS") 1821e52b07aaSAaron Conole actsmsg = None 1822e52b07aaSAaron Conole if acts_field is not None: 1823e52b07aaSAaron Conole actsmsg = acts_field 1824e52b07aaSAaron Conole 1825e52b07aaSAaron Conole print_str = "" 1826e52b07aaSAaron Conole 1827e52b07aaSAaron Conole if more: 1828e52b07aaSAaron Conole print_str += ufid_str + "," 1829e52b07aaSAaron Conole 1830e52b07aaSAaron Conole if keymsg is not None: 1831e52b07aaSAaron Conole print_str += keymsg.dpstr(maskmsg, more) 1832e52b07aaSAaron Conole 1833e52b07aaSAaron Conole stats = self.get_attr("OVS_FLOW_ATTR_STATS") 1834e52b07aaSAaron Conole if stats is None: 1835e52b07aaSAaron Conole print_str += " packets:0, bytes:0," 1836e52b07aaSAaron Conole else: 1837e52b07aaSAaron Conole print_str += " packets:%d, bytes:%d," % ( 1838e52b07aaSAaron Conole stats["packets"], 1839e52b07aaSAaron Conole stats["bytes"], 1840e52b07aaSAaron Conole ) 1841e52b07aaSAaron Conole 1842e52b07aaSAaron Conole used = self.get_attr("OVS_FLOW_ATTR_USED") 1843e52b07aaSAaron Conole print_str += " used:" 1844e52b07aaSAaron Conole if used is None: 1845e52b07aaSAaron Conole print_str += "never," 1846e52b07aaSAaron Conole else: 1847e52b07aaSAaron Conole used_time = int(used) 1848e52b07aaSAaron Conole cur_time_sec = time.clock_gettime(time.CLOCK_MONOTONIC) 1849e52b07aaSAaron Conole used_time = (cur_time_sec * 1000) - used_time 1850e52b07aaSAaron Conole print_str += "{}s,".format(used_time / 1000) 1851e52b07aaSAaron Conole 1852e52b07aaSAaron Conole print_str += " actions:" 1853e52b07aaSAaron Conole if ( 1854e52b07aaSAaron Conole actsmsg is None 1855e52b07aaSAaron Conole or "attrs" not in actsmsg 1856e52b07aaSAaron Conole or len(actsmsg["attrs"]) == 0 1857e52b07aaSAaron Conole ): 1858e52b07aaSAaron Conole print_str += "drop" 1859e52b07aaSAaron Conole else: 1860e52b07aaSAaron Conole print_str += actsmsg.dpstr(more) 1861e52b07aaSAaron Conole 1862e52b07aaSAaron Conole return print_str 1863e52b07aaSAaron Conole 1864918423fdSAaron Conole def parse(self, flowstr, actstr, dpidx=0): 1865918423fdSAaron Conole OVS_UFID_F_OMIT_KEY = 1 << 0 1866918423fdSAaron Conole OVS_UFID_F_OMIT_MASK = 1 << 1 1867918423fdSAaron Conole OVS_UFID_F_OMIT_ACTIONS = 1 << 2 1868918423fdSAaron Conole 1869918423fdSAaron Conole self["cmd"] = 0 1870918423fdSAaron Conole self["version"] = 0 1871918423fdSAaron Conole self["reserved"] = 0 1872918423fdSAaron Conole self["dpifindex"] = 0 1873918423fdSAaron Conole 1874918423fdSAaron Conole if flowstr.startswith("ufid:"): 1875918423fdSAaron Conole count = 5 1876918423fdSAaron Conole while flowstr[count] != ",": 1877918423fdSAaron Conole count += 1 1878918423fdSAaron Conole ufidstr = flowstr[5:count] 1879918423fdSAaron Conole flowstr = flowstr[count + 1 :] 1880918423fdSAaron Conole else: 1881918423fdSAaron Conole ufidstr = str(uuid.uuid4()) 1882918423fdSAaron Conole uuidRawObj = uuid.UUID(ufidstr).fields 1883918423fdSAaron Conole 1884918423fdSAaron Conole self["attrs"].append( 1885918423fdSAaron Conole [ 1886918423fdSAaron Conole "OVS_FLOW_ATTR_UFID", 1887918423fdSAaron Conole [ 1888918423fdSAaron Conole uuidRawObj[0], 1889918423fdSAaron Conole uuidRawObj[1] << 16 | uuidRawObj[2], 1890918423fdSAaron Conole uuidRawObj[3] << 24 1891918423fdSAaron Conole | uuidRawObj[4] << 16 1892918423fdSAaron Conole | uuidRawObj[5] & (0xFF << 32) >> 32, 1893918423fdSAaron Conole uuidRawObj[5] & (0xFFFFFFFF), 1894918423fdSAaron Conole ], 1895918423fdSAaron Conole ] 1896918423fdSAaron Conole ) 1897918423fdSAaron Conole self["attrs"].append( 1898918423fdSAaron Conole [ 1899918423fdSAaron Conole "OVS_FLOW_ATTR_UFID_FLAGS", 1900918423fdSAaron Conole int( 1901918423fdSAaron Conole OVS_UFID_F_OMIT_KEY 1902918423fdSAaron Conole | OVS_UFID_F_OMIT_MASK 1903918423fdSAaron Conole | OVS_UFID_F_OMIT_ACTIONS 1904918423fdSAaron Conole ), 1905918423fdSAaron Conole ] 1906918423fdSAaron Conole ) 1907918423fdSAaron Conole 1908918423fdSAaron Conole k = ovskey() 1909918423fdSAaron Conole m = ovskey() 1910918423fdSAaron Conole k.parse(flowstr, m) 1911918423fdSAaron Conole self["attrs"].append(["OVS_FLOW_ATTR_KEY", k]) 1912918423fdSAaron Conole self["attrs"].append(["OVS_FLOW_ATTR_MASK", m]) 1913918423fdSAaron Conole 1914918423fdSAaron Conole a = ovsactions() 1915918423fdSAaron Conole a.parse(actstr) 1916918423fdSAaron Conole self["attrs"].append(["OVS_FLOW_ATTR_ACTIONS", a]) 1917918423fdSAaron Conole 1918e52b07aaSAaron Conole def __init__(self): 1919e52b07aaSAaron Conole GenericNetlinkSocket.__init__(self) 1920e52b07aaSAaron Conole 1921e52b07aaSAaron Conole self.bind(OVS_FLOW_FAMILY, OvsFlow.ovs_flow_msg) 1922e52b07aaSAaron Conole 1923918423fdSAaron Conole def add_flow(self, dpifindex, flowmsg): 1924918423fdSAaron Conole """ 1925918423fdSAaron Conole Send a new flow message to the kernel. 1926918423fdSAaron Conole 1927918423fdSAaron Conole dpifindex should be a valid datapath obtained by calling 1928918423fdSAaron Conole into the OvsDatapath lookup 1929918423fdSAaron Conole 1930918423fdSAaron Conole flowmsg is a flow object obtained by calling a dpparse 1931918423fdSAaron Conole """ 1932918423fdSAaron Conole 1933918423fdSAaron Conole flowmsg["cmd"] = OVS_FLOW_CMD_NEW 1934918423fdSAaron Conole flowmsg["version"] = OVS_DATAPATH_VERSION 1935918423fdSAaron Conole flowmsg["reserved"] = 0 1936918423fdSAaron Conole flowmsg["dpifindex"] = dpifindex 1937918423fdSAaron Conole 1938918423fdSAaron Conole try: 1939918423fdSAaron Conole reply = self.nlm_request( 1940918423fdSAaron Conole flowmsg, 1941918423fdSAaron Conole msg_type=self.prid, 1942918423fdSAaron Conole msg_flags=NLM_F_REQUEST | NLM_F_ACK, 1943918423fdSAaron Conole ) 1944918423fdSAaron Conole reply = reply[0] 1945918423fdSAaron Conole except NetlinkError as ne: 1946918423fdSAaron Conole print(flowmsg) 1947918423fdSAaron Conole raise ne 1948918423fdSAaron Conole return reply 1949918423fdSAaron Conole 195076035fd1SAaron Conole def del_flows(self, dpifindex): 195176035fd1SAaron Conole """ 195276035fd1SAaron Conole Send a del message to the kernel that will drop all flows. 195376035fd1SAaron Conole 195476035fd1SAaron Conole dpifindex should be a valid datapath obtained by calling 195576035fd1SAaron Conole into the OvsDatapath lookup 195676035fd1SAaron Conole """ 195776035fd1SAaron Conole 195876035fd1SAaron Conole flowmsg = OvsFlow.ovs_flow_msg() 195976035fd1SAaron Conole flowmsg["cmd"] = OVS_FLOW_CMD_DEL 196076035fd1SAaron Conole flowmsg["version"] = OVS_DATAPATH_VERSION 196176035fd1SAaron Conole flowmsg["reserved"] = 0 196276035fd1SAaron Conole flowmsg["dpifindex"] = dpifindex 196376035fd1SAaron Conole 196476035fd1SAaron Conole try: 196576035fd1SAaron Conole reply = self.nlm_request( 196676035fd1SAaron Conole flowmsg, 196776035fd1SAaron Conole msg_type=self.prid, 196876035fd1SAaron Conole msg_flags=NLM_F_REQUEST | NLM_F_ACK, 196976035fd1SAaron Conole ) 197076035fd1SAaron Conole reply = reply[0] 197176035fd1SAaron Conole except NetlinkError as ne: 197276035fd1SAaron Conole print(flowmsg) 197376035fd1SAaron Conole raise ne 197476035fd1SAaron Conole return reply 197576035fd1SAaron Conole 1976e52b07aaSAaron Conole def dump(self, dpifindex, flowspec=None): 1977e52b07aaSAaron Conole """ 1978e52b07aaSAaron Conole Returns a list of messages containing flows. 1979e52b07aaSAaron Conole 1980e52b07aaSAaron Conole dpifindex should be a valid datapath obtained by calling 1981e52b07aaSAaron Conole into the OvsDatapath lookup 1982e52b07aaSAaron Conole 1983e52b07aaSAaron Conole flowpsec is a string which represents a flow in the dpctl 1984e52b07aaSAaron Conole format. 1985e52b07aaSAaron Conole """ 1986e52b07aaSAaron Conole msg = OvsFlow.ovs_flow_msg() 1987e52b07aaSAaron Conole 1988e52b07aaSAaron Conole msg["cmd"] = OVS_FLOW_CMD_GET 1989e52b07aaSAaron Conole msg["version"] = OVS_DATAPATH_VERSION 1990e52b07aaSAaron Conole msg["reserved"] = 0 1991e52b07aaSAaron Conole msg["dpifindex"] = dpifindex 1992e52b07aaSAaron Conole 1993e52b07aaSAaron Conole msg_flags = NLM_F_REQUEST | NLM_F_ACK 1994e52b07aaSAaron Conole if flowspec is None: 1995e52b07aaSAaron Conole msg_flags |= NLM_F_DUMP 1996e52b07aaSAaron Conole rep = None 1997e52b07aaSAaron Conole 1998e52b07aaSAaron Conole try: 1999e52b07aaSAaron Conole rep = self.nlm_request( 2000e52b07aaSAaron Conole msg, 2001e52b07aaSAaron Conole msg_type=self.prid, 2002e52b07aaSAaron Conole msg_flags=msg_flags, 2003e52b07aaSAaron Conole ) 2004e52b07aaSAaron Conole except NetlinkError as ne: 2005e52b07aaSAaron Conole raise ne 2006e52b07aaSAaron Conole return rep 2007e52b07aaSAaron Conole 20089feac87bSAaron Conole def miss(self, packetmsg): 20099feac87bSAaron Conole seq = packetmsg["header"]["sequence_number"] 20109feac87bSAaron Conole keystr = "(none)" 20119feac87bSAaron Conole key_field = packetmsg.get_attr("OVS_PACKET_ATTR_KEY") 20129feac87bSAaron Conole if key_field is not None: 20139feac87bSAaron Conole keystr = key_field.dpstr(None, True) 20149feac87bSAaron Conole 20159feac87bSAaron Conole pktdata = packetmsg.get_attr("OVS_PACKET_ATTR_PACKET") 20169feac87bSAaron Conole pktpres = "yes" if pktdata is not None else "no" 20179feac87bSAaron Conole 20189feac87bSAaron Conole print("MISS upcall[%d/%s]: %s" % (seq, pktpres, keystr), flush=True) 20199feac87bSAaron Conole 20209feac87bSAaron Conole def execute(self, packetmsg): 20219feac87bSAaron Conole print("userspace execute command") 20229feac87bSAaron Conole 20239feac87bSAaron Conole def action(self, packetmsg): 20249feac87bSAaron Conole print("userspace action command") 20259feac87bSAaron Conole 2026e52b07aaSAaron Conole 202774cc26f4SAaron Conoledef print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): 202825f16c87SAaron Conole dp_name = dp_lookup_rep.get_attr("OVS_DP_ATTR_NAME") 202925f16c87SAaron Conole base_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_STATS") 203025f16c87SAaron Conole megaflow_stats = dp_lookup_rep.get_attr("OVS_DP_ATTR_MEGAFLOW_STATS") 203125f16c87SAaron Conole user_features = dp_lookup_rep.get_attr("OVS_DP_ATTR_USER_FEATURES") 203225f16c87SAaron Conole masks_cache_size = dp_lookup_rep.get_attr("OVS_DP_ATTR_MASKS_CACHE_SIZE") 203325f16c87SAaron Conole 203425f16c87SAaron Conole print("%s:" % dp_name) 203525f16c87SAaron Conole print( 203625f16c87SAaron Conole " lookups: hit:%d missed:%d lost:%d" 203725f16c87SAaron Conole % (base_stats["hit"], base_stats["missed"], base_stats["lost"]) 203825f16c87SAaron Conole ) 203925f16c87SAaron Conole print(" flows:%d" % base_stats["flows"]) 204025f16c87SAaron Conole pkts = base_stats["hit"] + base_stats["missed"] 204125f16c87SAaron Conole avg = (megaflow_stats["mask_hit"] / pkts) if pkts != 0 else 0.0 204225f16c87SAaron Conole print( 204325f16c87SAaron Conole " masks: hit:%d total:%d hit/pkt:%f" 204425f16c87SAaron Conole % (megaflow_stats["mask_hit"], megaflow_stats["masks"], avg) 204525f16c87SAaron Conole ) 204625f16c87SAaron Conole print(" caches:") 204725f16c87SAaron Conole print(" masks-cache: size:%d" % masks_cache_size) 204825f16c87SAaron Conole 204925f16c87SAaron Conole if user_features is not None: 205025f16c87SAaron Conole print(" features: 0x%X" % user_features) 205125f16c87SAaron Conole 205225f16c87SAaron Conole # port print out 205325f16c87SAaron Conole for iface in ndb.interfaces: 205425f16c87SAaron Conole rep = vpl.info(iface.ifname, ifindex) 205525f16c87SAaron Conole if rep is not None: 205625f16c87SAaron Conole print( 205725f16c87SAaron Conole " port %d: %s (%s)" 205825f16c87SAaron Conole % ( 205925f16c87SAaron Conole rep.get_attr("OVS_VPORT_ATTR_PORT_NO"), 206025f16c87SAaron Conole rep.get_attr("OVS_VPORT_ATTR_NAME"), 206125f16c87SAaron Conole OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")), 206225f16c87SAaron Conole ) 206325f16c87SAaron Conole ) 206425f16c87SAaron Conole 206525f16c87SAaron Conole 206625f16c87SAaron Conoledef main(argv): 2067e52b07aaSAaron Conole nlmsg_atoms.ovskey = ovskey 2068e52b07aaSAaron Conole nlmsg_atoms.ovsactions = ovsactions 2069e52b07aaSAaron Conole 207092e37f20SAaron Conole # version check for pyroute2 207192e37f20SAaron Conole prverscheck = pyroute2.__version__.split(".") 207292e37f20SAaron Conole if int(prverscheck[0]) == 0 and int(prverscheck[1]) < 6: 207392e37f20SAaron Conole print("Need to upgrade the python pyroute2 package to >= 0.6.") 207492e37f20SAaron Conole sys.exit(0) 207592e37f20SAaron Conole 207625f16c87SAaron Conole parser = argparse.ArgumentParser() 207725f16c87SAaron Conole parser.add_argument( 207825f16c87SAaron Conole "-v", 207925f16c87SAaron Conole "--verbose", 208025f16c87SAaron Conole action="count", 208125f16c87SAaron Conole help="Increment 'verbose' output counter.", 2082e52b07aaSAaron Conole default=0, 208325f16c87SAaron Conole ) 208425f16c87SAaron Conole subparsers = parser.add_subparsers() 208525f16c87SAaron Conole 208625f16c87SAaron Conole showdpcmd = subparsers.add_parser("show") 208725f16c87SAaron Conole showdpcmd.add_argument( 208825f16c87SAaron Conole "showdp", metavar="N", type=str, nargs="?", help="Datapath Name" 208925f16c87SAaron Conole ) 209025f16c87SAaron Conole 209125f16c87SAaron Conole adddpcmd = subparsers.add_parser("add-dp") 209225f16c87SAaron Conole adddpcmd.add_argument("adddp", help="Datapath Name") 209325f16c87SAaron Conole adddpcmd.add_argument( 209425f16c87SAaron Conole "-u", 209525f16c87SAaron Conole "--upcall", 209625f16c87SAaron Conole action="store_true", 209725f16c87SAaron Conole help="Leave open a reader for upcalls", 209825f16c87SAaron Conole ) 209925f16c87SAaron Conole adddpcmd.add_argument( 210025f16c87SAaron Conole "-V", 210125f16c87SAaron Conole "--versioning", 210225f16c87SAaron Conole required=False, 210325f16c87SAaron Conole help="Specify a custom version / feature string", 210425f16c87SAaron Conole ) 210525f16c87SAaron Conole 210625f16c87SAaron Conole deldpcmd = subparsers.add_parser("del-dp") 210725f16c87SAaron Conole deldpcmd.add_argument("deldp", help="Datapath Name") 210825f16c87SAaron Conole 210974cc26f4SAaron Conole addifcmd = subparsers.add_parser("add-if") 211074cc26f4SAaron Conole addifcmd.add_argument("dpname", help="Datapath Name") 211174cc26f4SAaron Conole addifcmd.add_argument("addif", help="Interface name for adding") 211274cc26f4SAaron Conole addifcmd.add_argument( 21139feac87bSAaron Conole "-u", 21149feac87bSAaron Conole "--upcall", 21159feac87bSAaron Conole action="store_true", 21169feac87bSAaron Conole help="Leave open a reader for upcalls", 21179feac87bSAaron Conole ) 21189feac87bSAaron Conole addifcmd.add_argument( 211974cc26f4SAaron Conole "-t", 212074cc26f4SAaron Conole "--ptype", 212174cc26f4SAaron Conole type=str, 212274cc26f4SAaron Conole default="netdev", 212374cc26f4SAaron Conole choices=["netdev", "internal"], 212474cc26f4SAaron Conole help="Interface type (default netdev)", 212574cc26f4SAaron Conole ) 212674cc26f4SAaron Conole delifcmd = subparsers.add_parser("del-if") 212774cc26f4SAaron Conole delifcmd.add_argument("dpname", help="Datapath Name") 212874cc26f4SAaron Conole delifcmd.add_argument("delif", help="Interface name for adding") 212974cc26f4SAaron Conole 2130e52b07aaSAaron Conole dumpflcmd = subparsers.add_parser("dump-flows") 2131e52b07aaSAaron Conole dumpflcmd.add_argument("dumpdp", help="Datapath Name") 2132e52b07aaSAaron Conole 2133918423fdSAaron Conole addflcmd = subparsers.add_parser("add-flow") 2134918423fdSAaron Conole addflcmd.add_argument("flbr", help="Datapath name") 2135918423fdSAaron Conole addflcmd.add_argument("flow", help="Flow specification") 2136918423fdSAaron Conole addflcmd.add_argument("acts", help="Flow actions") 2137918423fdSAaron Conole 213876035fd1SAaron Conole delfscmd = subparsers.add_parser("del-flows") 213976035fd1SAaron Conole delfscmd.add_argument("flsbr", help="Datapath name") 214076035fd1SAaron Conole 214125f16c87SAaron Conole args = parser.parse_args() 214225f16c87SAaron Conole 2143e52b07aaSAaron Conole if args.verbose > 0: 2144e52b07aaSAaron Conole if args.verbose > 1: 2145e52b07aaSAaron Conole logging.basicConfig(level=logging.DEBUG) 2146e52b07aaSAaron Conole 21479feac87bSAaron Conole ovspk = OvsPacket() 214825f16c87SAaron Conole ovsdp = OvsDatapath() 21499feac87bSAaron Conole ovsvp = OvsVport(ovspk) 2150e52b07aaSAaron Conole ovsflow = OvsFlow() 215125f16c87SAaron Conole ndb = NDB() 215225f16c87SAaron Conole 21534c3157ddSAaron Conole sys.setrecursionlimit(100000) 21544c3157ddSAaron Conole 215525f16c87SAaron Conole if hasattr(args, "showdp"): 215625f16c87SAaron Conole found = False 215725f16c87SAaron Conole for iface in ndb.interfaces: 215825f16c87SAaron Conole rep = None 215925f16c87SAaron Conole if args.showdp is None: 216025f16c87SAaron Conole rep = ovsdp.info(iface.ifname, 0) 216125f16c87SAaron Conole elif args.showdp == iface.ifname: 216225f16c87SAaron Conole rep = ovsdp.info(iface.ifname, 0) 216325f16c87SAaron Conole 216425f16c87SAaron Conole if rep is not None: 216525f16c87SAaron Conole found = True 216674cc26f4SAaron Conole print_ovsdp_full(rep, iface.index, ndb, ovsvp) 216725f16c87SAaron Conole 216825f16c87SAaron Conole if not found: 216925f16c87SAaron Conole msg = "No DP found" 217025f16c87SAaron Conole if args.showdp is not None: 217125f16c87SAaron Conole msg += ":'%s'" % args.showdp 217225f16c87SAaron Conole print(msg) 217325f16c87SAaron Conole elif hasattr(args, "adddp"): 21749feac87bSAaron Conole rep = ovsdp.create(args.adddp, args.upcall, args.versioning, ovspk) 217525f16c87SAaron Conole if rep is None: 217625f16c87SAaron Conole print("DP '%s' already exists" % args.adddp) 217725f16c87SAaron Conole else: 217825f16c87SAaron Conole print("DP '%s' added" % args.adddp) 21799feac87bSAaron Conole if args.upcall: 21809feac87bSAaron Conole ovspk.upcall_handler(ovsflow) 218125f16c87SAaron Conole elif hasattr(args, "deldp"): 218225f16c87SAaron Conole ovsdp.destroy(args.deldp) 218374cc26f4SAaron Conole elif hasattr(args, "addif"): 218474cc26f4SAaron Conole rep = ovsdp.info(args.dpname, 0) 218574cc26f4SAaron Conole if rep is None: 218674cc26f4SAaron Conole print("DP '%s' not found." % args.dpname) 218774cc26f4SAaron Conole return 1 21889feac87bSAaron Conole dpindex = rep["dpifindex"] 218974cc26f4SAaron Conole rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype) 219074cc26f4SAaron Conole msg = "vport '%s'" % args.addif 219174cc26f4SAaron Conole if rep and rep["header"]["error"] is None: 219274cc26f4SAaron Conole msg += " added." 219374cc26f4SAaron Conole else: 219474cc26f4SAaron Conole msg += " failed to add." 21959feac87bSAaron Conole if args.upcall: 21969feac87bSAaron Conole if rep is None: 21979feac87bSAaron Conole rep = ovsvp.reset_upcall(dpindex, args.addif, ovspk) 21989feac87bSAaron Conole ovsvp.upcall_handler(ovsflow) 219974cc26f4SAaron Conole elif hasattr(args, "delif"): 220074cc26f4SAaron Conole rep = ovsdp.info(args.dpname, 0) 220174cc26f4SAaron Conole if rep is None: 220274cc26f4SAaron Conole print("DP '%s' not found." % args.dpname) 220374cc26f4SAaron Conole return 1 220474cc26f4SAaron Conole rep = ovsvp.detach(rep["dpifindex"], args.delif) 220574cc26f4SAaron Conole msg = "vport '%s'" % args.delif 220674cc26f4SAaron Conole if rep and rep["header"]["error"] is None: 220774cc26f4SAaron Conole msg += " removed." 220874cc26f4SAaron Conole else: 220974cc26f4SAaron Conole msg += " failed to remove." 2210e52b07aaSAaron Conole elif hasattr(args, "dumpdp"): 2211e52b07aaSAaron Conole rep = ovsdp.info(args.dumpdp, 0) 2212e52b07aaSAaron Conole if rep is None: 2213e52b07aaSAaron Conole print("DP '%s' not found." % args.dumpdp) 2214e52b07aaSAaron Conole return 1 2215e52b07aaSAaron Conole rep = ovsflow.dump(rep["dpifindex"]) 2216e52b07aaSAaron Conole for flow in rep: 2217e52b07aaSAaron Conole print(flow.dpstr(True if args.verbose > 0 else False)) 2218918423fdSAaron Conole elif hasattr(args, "flbr"): 2219918423fdSAaron Conole rep = ovsdp.info(args.flbr, 0) 2220918423fdSAaron Conole if rep is None: 2221918423fdSAaron Conole print("DP '%s' not found." % args.flbr) 2222918423fdSAaron Conole return 1 2223918423fdSAaron Conole flow = OvsFlow.ovs_flow_msg() 2224918423fdSAaron Conole flow.parse(args.flow, args.acts, rep["dpifindex"]) 2225918423fdSAaron Conole ovsflow.add_flow(rep["dpifindex"], flow) 222676035fd1SAaron Conole elif hasattr(args, "flsbr"): 222776035fd1SAaron Conole rep = ovsdp.info(args.flsbr, 0) 222876035fd1SAaron Conole if rep is None: 222976035fd1SAaron Conole print("DP '%s' not found." % args.flsbr) 223076035fd1SAaron Conole ovsflow.del_flows(rep["dpifindex"]) 223125f16c87SAaron Conole 223225f16c87SAaron Conole return 0 223325f16c87SAaron Conole 223425f16c87SAaron Conole 223525f16c87SAaron Conoleif __name__ == "__main__": 223625f16c87SAaron Conole sys.exit(main(sys.argv)) 2237