def do_create_ap(self, port_list, count, verbose_level, ap_cert, ap_privkey, ap_ca_priv): '''Create AP(s) on port''' if count < 1: raise TRexError('Count should be greated than zero') if not port_list: raise TRexError('Please specify TRex ports where to add AP(s)') bu_mac, bu_ip, _ = self.ap_manager._gen_ap_params() init_ports = [port for port in port_list if port not in self.ap_manager.service_ctx] ap_names = [] success = False try: self.ap_manager.init(init_ports) # implicitly for console for port in port_list: for _ in range(count): ap_params = self.ap_manager._gen_ap_params() self.ap_manager.create_ap(port, *ap_params, verbose_level = verbose_level, rsa_ca_priv_file = ap_ca_priv, rsa_priv_file = ap_privkey, rsa_cert_file = ap_cert) ap_names.append(ap_params[0]) assert ap_names self.ap_manager.join_aps(ap_names) success = True finally: if not success: for name in ap_names: # rollback self.ap_manager.remove_ap(name) self.ap_manager.set_base_values(mac = bu_mac, ip = bu_ip) close_ports = [port for port in init_ports if port in self.ap_manager.service_ctx] if close_ports: self.ap_manager.close(close_ports)
def do_add_client(self, ap_ids, count): '''Add client(s) to AP(s)''' if count < 1 or count > 200: raise TRexError('Count of clients should be within range 1-200') ap_ids = ap_ids or self.ap_manager.aps bu_mac, bu_ip = self.ap_manager._gen_client_params() client_ips = [] success = False try: for ap_id in ap_ids: for _ in range(count): client_params = self.ap_manager._gen_client_params() self.ap_manager.create_client( *client_params, ap_id=self.ap_manager._get_ap_by_id(ap_id)) client_ips.append(client_params[1]) self.ap_manager.join_clients(client_ips) success = True finally: if not success: for ip in client_ips: # rollback self.ap_manager.remove_client(ip) self.ap_manager.set_base_values(client_mac=bu_mac, client_ip=bu_ip)
def do_start(self, client_ids, file_path, multiplier, tunables, total_mult): '''Start traffic on behalf on client(s).''' if not client_ids: clients = self.ap_manager.clients else: clients = set( [self.ap_manager._get_client_by_id(id) for id in client_ids]) if len(client_ids) != len(clients): raise TRexError('Client IDs should be unique') if not clients: raise TRexError('No clients to start traffic on behalf of them!') ports = list(set([client.ap.port_id for client in clients])) # stop ports if needed active_ports = list_intersect(self.trex_client.get_active_ports(), ports) if active_ports: self.trex_client.stop(active_ports) # remove all streams self.trex_client.remove_all_streams(ports) # pack the profile try: tunables = tunables or {} for client in clients: profile = STLProfile.load(file_path, direction=tunables.get( 'direction', client.ap.port_id % 2), port_id=client.ap.port_id, **tunables) self.ap_manager.add_streams(client, profile.get_streams()) except STLError as e: msg = bold("\nError loading profile '%s'" % file_path) self.ap_manager.log(msg + '\n') self.ap_manager.log(e.brief() + "\n") self.trex_client.start(ports=ports, mult=multiplier, force=True, total=total_mult) return RC_OK()
def plugin_unload(self): if self.console is None: raise TRexError( "Trex console must be provided in order to unload emu plugin") self.console.unload_client_plugin_functions( func_prefix=Emu_Plugin.EMU_PREFIX) self.c.disconnect()
def plugin_load(self): if self.console is None: raise TRexError( 'Trex console must be provided in order to load emu plugin') c = self.console.client c_mode = c.get_mode() if c_mode != "ASTF": raise TRexError( 'TRex client mode must be ASTF, current client mode: %s' % c_mode) if not hasattr(self.console, 'emu_client'): raise TRexError( 'Cannot find trex emu client in console, load emu plugin first' ) self.emu_c = self.console.emu_client self.astf_c = c
def do_reconnect(self, device_ids): '''Reconnect disconnected AP(s) or Client(s).''' device_ids = device_ids or ([a.name for a in self.ap_manager.aps] + [c.ip for c in self.ap_manager.clients]) ports = set() aps = set() clients = set() err_ids = set() for device_id in device_ids: try: ap = self.ap_manager._get_ap_by_id(device_id) aps.add(ap) clients |= set(ap.clients) ports.add(ap.port_id) except: try: client = self.ap_manager._get_client_by_id(device_id) clients.add(client) aps.add(client.ap) ports.add(client.ap.port_id) except: err_ids.add(device_id) if err_ids: raise TRexError('Invalid IDs: %s' % ', '.join(sorted(err_ids, key=natural_sorted_key))) if not self.ap_manager.bg_client.is_connected(): self.ap_manager.bg_client.connect() for port_id in ports: if port_id in self.ap_manager.service_ctx: if not self.ap_manager.service_ctx[port_id]['bg'].is_running(): self.ap_manager.service_ctx[port_id]['bg'].run() non_init_ports = [ p for p in ports if p not in self.ap_manager.service_ctx ] not_joined_aps = [ a for a in aps if not (a.is_connected and a.is_dtls_established) ] not_assoc_clients = [ c for c in clients if not (c.is_associated and c.seen_arp_reply) ] if not (non_init_ports or not_joined_aps or not_assoc_clients): self.ap_manager.log( bold('Nothing to reconnect, everything works fine.')) return while non_init_ports: self.ap_manager.init(non_init_ports[:10]) non_init_ports = non_init_ports[10:] while not_joined_aps: self.ap_manager.join_aps(not_joined_aps[:10]) not_joined_aps = not_joined_aps[10:] while not_assoc_clients: self.ap_manager.join_clients(not_assoc_clients[:20]) not_assoc_clients = not_assoc_clients[20:]
def plugin_load(self): if self.console is None: raise TRexError( "Trex console must be provided in order to load emu plugin") client = self.console.client verbose = client.logger.get_verbose() # taking parameters from original self.c = EMUClient(server=self.console.emu_server, verbose_level=verbose, logger=client.logger) self.c.connect() self.console.load_client_plugin_functions( self.c, func_prefix=Emu_Plugin.EMU_PREFIX)
def do_proxy(self, proxy_wired_port, proxy_wireless_port, proxy_dest_mac, proxy_filter_wlc_packets, proxy_disable, proxy_clear): '''Proxify traffic between wireless side (Stateful TRex) and wired side (WLC).''' if proxy_clear: self.ap_manager.disable_proxy_mode(ignore_errors=True) elif any([proxy_wired_port, proxy_wireless_port]): if proxy_wired_port is None: raise TRexError('Must specify wired port') if proxy_wireless_port is None: raise TRexError('Must specify wireless port') if proxy_disable: self.ap_manager.disable_proxy_mode( ports=[proxy_wired_port, proxy_wireless_port]) else: if proxy_wireless_port not in self.trex_client.ports: raise TRexError('Invalid wireless port ID: %s' % proxy_wireless_port) port = self.trex_client.ports[proxy_wireless_port] if not port.is_service_mode_on(): port.set_service_mode(True) self.ap_manager.enable_proxy_mode(proxy_wired_port, proxy_wireless_port, proxy_dest_mac, proxy_filter_wlc_packets) else: counters_dict = { 'BPF reject': 'm_bpf_rejected', 'IP convert ERR': 'm_ip_convert_err', 'Map not found': 'm_map_not_found', 'Not IP pkt': 'm_not_ip', 'Pkt too large': 'm_too_large_pkt', 'Pkt too small': 'm_too_small_pkt', 'Pkts from WLC': 'm_pkt_from_wlc', 'TX ERR': 'm_tx_err', 'TX OK': 'm_tx_ok', } proxy_table = text_tables.Texttable(max_width=200) categories = ['Port', 'Counters', 'Clients'] proxy_table.header([bold(c) for c in categories]) proxy_table.set_cols_align(['l'] * len(categories)) proxy_table.set_deco(15) for port_id in sorted(self.trex_client.get_acquired_ports()): data = self.ap_manager.get_proxy_stats( ports=[port_id], decode_map=False)[port_id] if not data or not data['is_active']: continue row = [ 'ID: %s\n(%s)\nPair: %s' % (port_id, 'WLAN' if data['is_wireless_side'] else 'LAN', data['pair_port_id']) ] counters_table = text_tables.Texttable() counters_table.set_deco(0) counters_table.set_cols_dtype(['t', 'i']) counters_table.set_cols_align(['l'] * 2) for k in sorted(counters_dict.keys()): val = data['counters'][counters_dict[k]] if val: counters_table.add_row(['%s:' % k, val]) row.append(counters_table.draw()) clients = '' clients_arr = sorted(data['capwap_map'].keys(), key=natural_sorted_key) if len(clients_arr) > 1: first_ip_num = ipv4_str_to_num( is_valid_ipv4_ret(clients_arr[0])) last_ip_num = ipv4_str_to_num( is_valid_ipv4_ret(clients_arr[-1])) if first_ip_num == last_ip_num - len( clients_arr) + 1: # continuous range of IPs clients = 'From %s to %s' % (clients_arr[0], clients_arr[-1]) else: while True: clients_row = [ '%15s' % ip for ip in clients_arr[0:5] ] if not clients_row: break clients += ', '.join(clients_row) + '\n' clients_arr = clients_arr[5:] else: clients = clients_arr[0] row.append(clients) proxy_table.add_row(row) self.ap_manager.log(proxy_table.draw())
def do_sync_topo(self): ''' Sync astf topology with current Emu server data. Requires resolved dgw mac address and ipv4 and ipv6 dgw resolved macs must not be different. ''' emu_c, astf_c = self.emu_c, self.astf_c emu_topo = ASTFTopology() emu_ns_and_c = emu_c.get_all_ns_and_clients() empty_ip_val = '' for ns in emu_ns_and_c: # take only clients ns if ns['vport'] % 2: continue port = str(ns['vport']) vlans = filter(lambda x: x != 0, ns.get('tci', [])) if len(vlans) > 1: raise TRexError( 'Cannot convert topo when namespace has more than 1 vlan') elif len(vlans) == 1: vlan = vlans[0] else: vlan = 0 for c_i, c in enumerate(ns.get('clients', []), start=1): port_id = '%s.%s' % (port, c_i) src_mac = c['mac'] # mac is mandatory for client src_ipv4 = c.get('ipv4', empty_ip_val) src_ipv6 = c.get('ipv6', empty_ip_val) if src_ipv4 == '0.0.0.0' or src_ipv4 == empty_ip_val: raise TRexError( 'Cannot sync: node with mac: "%s" has no ipv4 address' % src_mac) if c.get('dgw') and c['dgw'].get('resolve'): ipv4_dst = c['dgw'].get('rmac') else: ipv4_dst = None if c.get('ipv6_dgw') and c['ipv6_dgw'].get('resolve'): ipv6_dst = c['ipv6_dgw'].get('rmac') else: ipv6_dst = None if ipv4_dst is None and ipv6_dst is None: raise TRexError( 'Cannot sync: node with mac: "%s" has no resolved default gateway mac address' % src_mac) if ipv4_dst is not None and ipv6_dst is not None and ipv4_dst != ipv6_dst: raise TRexError( 'Cannot sync: node with mac: "%s" has different resolved default gateway mac address for ipv4 and ipv6' % src_mac) emu_topo.add_vif(port_id=port_id, src_mac=src_mac, src_ipv4=src_ipv4, src_ipv6=src_ipv6, vlan=vlan) emu_topo.add_gw( port_id=port_id, src_start=src_ipv4, src_end=src_ipv4, dst=ipv4_dst if ipv4_dst is not None else ipv6_dst) astf_c.topo_clear() astf_c.topo_load(emu_topo) astf_c.topo_resolve() astf_c.logger.info(format_text("emu topo synced\n", 'green', 'bold'))
def do_proxy(self, proxy_wired_port, proxy_wireless_port, proxy_disable, proxy_clear): '''Proxify traffic between wireless side (Stateful TRex) and wired side (WLC).''' if proxy_clear: self.ap_manager.disable_proxy_mode(ignore_errors=True) elif any([proxy_wired_port, proxy_wireless_port]): if proxy_wired_port is None: raise TRexError('Must specify wired port') if proxy_wireless_port is None: raise TRexError('Must specify wireless port') if proxy_disable: self.ap_manager.disable_proxy_mode( ports=[proxy_wired_port, proxy_wireless_port]) else: assert proxy_wireless_port in self.trex_client.ports, 'Invalid wireless port ID: %s' % proxy_wireless_port port = self.trex_client.ports[proxy_wireless_port] if not port.is_service_mode_on(): port.set_service_mode(True) self.ap_manager.enable_proxy_mode( wired_port=proxy_wired_port, wireless_port=proxy_wireless_port) else: counters_dict = { 'BPF reject': 'm_bpf_rejected', 'IP convert err': 'm_ip_convert_err', 'Alloc error': 'm_map_alloc_err', 'Map not found': 'm_map_not_found', 'Not IP pkt': 'm_not_ip', 'Pkt too large': 'm_too_large_pkt', 'Pkt too small': 'm_too_small_pkt', 'TX err': 'm_tx_err', 'TX OK': 'm_tx_ok', } proxy_table = text_tables.Texttable(max_width=200) categories = ['Port', 'Counters', 'Wrapping map per client'] proxy_table.header([bold(c) for c in categories]) proxy_table.set_cols_align(['l'] * len(categories)) proxy_table.set_deco(15) for port_id in sorted(self.trex_client.get_acquired_ports()): data = self.ap_manager.get_proxy_stats( ports=[port_id], decode_map=True)[port_id] if not data or not data['is_active']: continue row = [ 'ID: %s\n(%s)\nPair: %s' % (port_id, 'WLAN' if data['is_wireless_side'] else 'LAN', data['pair_port_id']) ] counters_table = text_tables.Texttable() counters_table.set_deco(0) counters_table.set_cols_dtype(['t', 'i']) counters_table.set_cols_align(['l'] * 2) for k in sorted(counters_dict.keys()): val = data['counters'][counters_dict[k]] if not val: continue counters_table.add_row(['%s:' % k, val]) row.append(counters_table.draw()) mappings = [] for client_ip in sorted(list(data['capwap_map'].keys()), key=natural_sorted_key): pkt_cmd = data['capwap_map'][client_ip] if len(pkt_cmd) > 100: pkt_cmd = pkt_cmd[:97] + '...' mappings.append('%s: %s' % (client_ip, pkt_cmd)) row.append('\n'.join(mappings)) proxy_table.add_row(row) self.ap_manager.log(proxy_table.draw())
def _call_method(self, method_name, method_params): rc = self.rpc.transmit(method_name=method_name, params=method_params) if not rc: raise TRexError(rc.err()) return rc.data()
def err(name, val, reason): raise TRexError('Validation error, argument "{name}" with value "{val}"\nReason: {reason}'.format(name=name, val=val, reason=reason))