From 2b2be43925f3425e0c7c10f61123c2a6102b0b65 Mon Sep 17 00:00:00 2001 From: Gulam Mohamed Date: Tue, 7 Jan 2025 10:12:00 +0000 Subject: [PATCH 1/2] Add more info to iscsi dump info Orabug: 34461976 Signed-off-by: Gulam Mohamed --- drgn_tools/iscsi.py | 243 +++++++++++++++++++++++++++++++------------- 1 file changed, 175 insertions(+), 68 deletions(-) diff --git a/drgn_tools/iscsi.py b/drgn_tools/iscsi.py index e52643b..5efe0e6 100644 --- a/drgn_tools/iscsi.py +++ b/drgn_tools/iscsi.py @@ -5,6 +5,12 @@ """ import argparse from typing import Iterator +from typing import Dict +from typing import Any + +import drgn +import socket +from drgn import cast from drgn import Object from drgn import Program @@ -21,8 +27,83 @@ from drgn_tools.table import print_dictionary from drgn_tools.util import enum_name_get -ISCSI_SESSION_STATES = ["LOGGED_IN", "FAILED", "FREE"] +# Available Hardware and Software iSCSI Transports +iscsi_transports = ["bnx2i", + "cxgb3i", + "cxgb4i", + "iser", + "qedi", + "bfin dpmc", + "h1940-bt", + "tcp"] + +# iSCSI Session States +iscsi_session_states = ["UNKNOWN", + "FREE", + "LOGGED_IN", + "FAILED", + "TERMINATE", + "IN_RECOVERY", + "RECOVERY_FAILED", + "LOGGING_OUT" + ] + +# iSCSI Connection Stages +iscsi_connection_stages = ["INITIAL_STAGE", + "STARTED", + "STOPPED", + "CLEANUP_WAIT" + ] +# iSCSI Connection States +iscsi_connection_states = ["UP", + "DOWN", + "FAILED", + "BOUND" + ] + +# SCSI device States +scsi_device_states = ["unknown", + "created", + "running", + "cancel", + "del", + "quiesce", + "offline", + "transport offline", + "blocked", + "created block" + ] + +# Scsi_Host states +scsi_host_states = ["UNKNOWN", + "CREATED", + "RUNNING", + "CANCEL", + "DEL", + "RECOVERY", + "CANCEL_RECOVERY", + "DEL_RECOVERY" + ] +# Sub-Headings +sub_headings = ["Interface", + "CHAP", + "Timeouts", + "Negotiated iSCSI params", + "Attached SCSI devices" + ] +def print_iscsi_info(info: Dict[str, Any]) -> None: + for line in info: + if "Target IQN" in line: + print(f"{line}: {info[line]}") + elif line == "Current Portal" or line == "Persistent Portal": + print(f"\t{line}: {info[line]}") + elif any(line in s for s in sub_headings): + print(f"\t\t"+"*" * (len(line) + 1)) + print(f"\t\t{line}: {info[line]}") + print(f"\t\t"+"*" * (len(line) + 1)) + else: + print(f"\t\t{line}: {info[line]}") def for_each_iscsi_host(prog: Program) -> Iterator[Object]: """ @@ -62,8 +143,95 @@ def for_each_iscsi_session(prog: Program) -> Iterator[Object]: address=cls_session.dd_data, ) +def get_iscsi_info(iscsi_conn: Object, prog: Program ) -> Dict[str, Any]: -def print_iscsi_sessions(prog: Program) -> None: + iscsi_session = iscsi_conn.session + iscsi_cls_conn = iscsi_conn.cls_conn + iscsi_cls_session = iscsi_session.cls_session + iscsi_tcp_conn = cast("struct iscsi_tcp_conn *", iscsi_conn.dd_data) + iscsi_sw_tcp_conn = cast("struct iscsi_sw_tcp_conn *", iscsi_tcp_conn.dd_data) + iscsi_socket = iscsi_sw_tcp_conn.sock + iscsi_sock = iscsi_socket.sk + scsi_host = iscsi_session.host + iscsi_host_data = scsi_host.hostdata + iscsi_host = cast("struct iscsi_host *", iscsi_host_data) + + try: + if iscsi_sock.__sk_common.skc_family == 2: + current_address = iscsi_sock.__sk_common.skc_daddr + current_address = prog.read_u32(current_address.address_of_()) + current_ip = socket.inet_ntoa(bytes([(current_address) & 0xFF, + (current_address >> 8) & 0xFF, + (current_address >> 16) & 0xFF, + (current_address >> 24) & 0xFF])) + current_port = iscsi_sock.__sk_common.skc_dport + current_port = prog.read_u16(current_port.address_of_()) + current_port = socket.ntohs(current_port) + local_address = iscsi_sock.__sk_common.skc_rcv_saddr + local_address = prog.read_u32(local_address.address_of_()) + local_ip = socket.inet_ntoa(bytes([(local_address) & 0xFF, + (local_address >> 8) & 0xFF, + (local_address >> 16) & 0xFF, + (local_address >> 24) & 0xFF])) + except drgn.FaultError: + current_ip = "[default]" + local_ip = "[default]" + current_port = "" + return { + "Target IQN":escape_ascii_string(iscsi_session.targetname.string_()), + "Current Portal":(current_ip+":"+str(current_port)), + "Persistent Portal": escape_ascii_string(iscsi_conn.persistent_address.string_())+ + ":"+str(iscsi_conn.persistent_port.value_())+","+ + str(iscsi_session.tpgt.value_()), + "Interface":"", + "Iface Name":escape_ascii_string(iscsi_session.ifacename.string_()), + "Iface Transport":escape_ascii_string(iscsi_cls_session.transport.name.string_()), + "Iface Initiatorname": escape_ascii_string(iscsi_session.initiatorname.string_()), + "Iface IPaddress": local_ip, + "Iface HWaddress": escape_ascii_string(iscsi_host.hwaddress.string_()) if iscsi_host.hwaddress else "default", + "Iface Netdev": escape_ascii_string(iscsi_host.netdev.string_()) if iscsi_host.netdev else "default", + "SID": iscsi_cls_session.sid.value_(), + "iSCSI Connection State": iscsi_connection_states[iscsi_cls_conn.state.value_()], + "iSCSI Session State": iscsi_session_states[iscsi_session.state.value_()], + "Internal iscsid Session State": iscsi_session_states[iscsi_session.state.value_()], + "Timeouts":"", + "Recovery Timeout": iscsi_cls_session.recovery_tmo.value_(), + "Target Reset Timeout": iscsi_session.tgt_reset_timeout.value_(), + "LUN Reset Timeout": iscsi_session.lu_reset_timeout.value_(), + "Abort Timeout": iscsi_session.abort_timeout.value_(), + "CHAP":"", + "username": (escape_ascii_string(iscsi_session.username.string_()) if iscsi_session.username else ""), + "password": (escape_ascii_string(iscsi_session.password.string_()) if iscsi_session.password else "********"), + "username_in": (escape_ascii_string(iscsi_session.username_in.string_()) if iscsi_session.username_in else ""), + "password_in": (escape_ascii_string(iscsi_session.password_in.string_()) if iscsi_session.password_in else "********"), + "Negotiated iSCSI params":"", + "HeaderDigest": (iscsi_conn.hdrdgst_en.value_() if iscsi_conn.hdrdgst_en else "None"), + "DataDigest": (iscsi_conn.datadgst_en.value_() if iscsi_conn.datadgst_en else "None"), + "MaxRecvDataSegmentLength": iscsi_conn.max_recv_dlength.value_(), + "MaxXmitDataSegmentLength": iscsi_conn.max_xmit_dlength.value_(), + "FirstBurstLength": iscsi_session.first_burst.value_(), + "MaxBurstLength": iscsi_session.max_burst.value_(), + "ImmediateData": ("Yes" if iscsi_session.imm_data_en.value_() else "No"), + "InitialR2T": ("Yes" if iscsi_session.initial_r2t_en.value_() else "No"), + "MaxOutstandingR2T": iscsi_session.max_r2t.value_(), + "Attached SCSI devices":"", + f"Host Number: {scsi_host.host_no.value_()} State": scsi_host_states[scsi_host.shost_state.value_()] + } + +def get_iscsi_disks_info(scsi_device: Object, prog: Program) -> Dict[str, Any]: + scsi_host = scsi_device.host + lun = scsi_device.lun.value_() + host_no = scsi_host.host_no.value_() + Id = scsi_device.id.value_() + channel = scsi_device.channel.value_() + sdev_state = scsi_device_states[scsi_device.sdev_state.value_()] + sdev_name = scsi_device_name(prog, scsi_device) + return { + f"scsi{host_no} channel {channel} id {Id} Lun": lun, + f"\tAttached scsi disk {sdev_name}\tState": sdev_state + } + +def dump_iscsi_sessions(prog: Program) -> None: """ Dump iscsi sessions. @@ -73,76 +241,15 @@ def print_iscsi_sessions(prog: Program) -> None: print(msg) return - output = {} - for session in reversed(list(for_each_iscsi_session(prog))): - print("**********") conn = session.leadconn - persistent_address = escape_ascii_string( - conn.persistent_address.string_() - ) - persistent_port = int(conn.persistent_port) - output[ - "Scsi_Host" - ] = f"host{session.host.host_no.value_()} ({hex(session.host.value_())})" - output["Session"] = hex(session.address_of_()) - output["SID"] = str(int(session.cls_session.sid)) - output["Persistent Portal"] = f"{persistent_address}:{persistent_port}" - output["Iface Name"] = escape_ascii_string(session.ifacename.string_()) - output["Session State"] = ISCSI_SESSION_STATES[ - session.cls_session.state - ] - connstate = enum_type_to_class( - prog.type("enum iscsi_connection_state"), "connstate" - ) - output["Connection State"] = str( - enum_name_get( - connstate, - conn.cls_conn.state, - "UNKNOWN", - ) - ) - output["Initiatorname"] = escape_ascii_string( - session.initiatorname.string_() - ) - output["Targetname"] = escape_ascii_string( - session.targetname.string_() - ) - - print_dictionary(output) - - print("Attached SCSI devices: ") - print("**********") - print( - "Host Number: {} STATE: {}".format( - session.host.host_no.value_(), - session.host.shost_state.format_(type_name=False), - ) - ) + iscsi_info = get_iscsi_info(conn, prog) + print_iscsi_info(iscsi_info) for scsi_dev in for_each_scsi_host_device(prog, session.host): - name = scsi_device_name(prog, scsi_dev) - print( - "scsi{} Channel {} Id {} Lun: {}".format( - session.host.host_no.value_(), - int(scsi_dev.channel), - int(scsi_dev.id), - int(scsi_dev.lun), - ) - ) - sdev_state = enum_type_to_class( - prog.type("enum scsi_device_state"), "sdev_state" - ) - state = enum_name_get( - sdev_state, - scsi_dev.sdev_state, - "UNKNOWN", - ) - print(" Attached iscsi disk: {} State: {}".format(name, state)) - - print() - + iscsi_disks_info = get_iscsi_disks_info(scsi_dev, prog) + print_iscsi_info(iscsi_disks_info) class Iscsi(CorelensModule): """ @@ -153,4 +260,4 @@ class Iscsi(CorelensModule): skip_unless_have_kmod = ["libiscsi", "scsi_transport_iscsi"] def run(self, prog: Program, args: argparse.Namespace) -> None: - print_iscsi_sessions(prog) + dump_iscsi_sessions(prog) From c07041524fc3c50a41952f8154cc4db7b19f91db Mon Sep 17 00:00:00 2001 From: Gulam Mohamed Date: Tue, 7 Jan 2025 10:28:45 +0000 Subject: [PATCH 2/2] Correct the name of test function Correct the name of the test function from print_iscsi_sessions() to dump_iscsi_sessions() --- tests/test_iscsi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_iscsi.py b/tests/test_iscsi.py index fa1247c..eb0b925 100644 --- a/tests/test_iscsi.py +++ b/tests/test_iscsi.py @@ -4,4 +4,4 @@ def test_iscsi(prog): - iscsi.print_iscsi_sessions(prog) + iscsi.dump_iscsi_sessions(prog)