Gi-z/CSIKit

IWL5300 realtime csi gathering

Closed this issue · 7 comments

Hay @Gi-z ,
Your tool is very helpful extracting CSI of the Intel5300. Thanks for sharing this.

I see that you implemented some legacy code that extracts CSI directly from the UPD stream. why you discarded this functionality?
The comments of the IWLBreamformReader says that it extracts realtime Data, but the functions seems to be not implemented yet.
In your readme is describing that it is only possible to read the .pcap and die .data files.

I my use-case it would be great to extract CSI at realtime.

Gi-z commented

Hi, that code is functional but incomplete. My only test system using IWL5300 encounters a buffer overflow after reading CSI in real-time for longer than 1 minute. I am inexperienced with Linux sockets and as such haven't been able to effectively debug this issue. For now there may be better solutions for this elsewhere, but I may be able to investigate this again soon.

Are you sure that a buffer overflow happend? Because currently I am using the https://github.com/pgawlowicz/linux-80211n-csitool-supplementary/blob/master/python/netlink.py code to extract csi at real time and have no problems.
this code seems to be very close to yours.

a few times the driver crashes after collecting much data but I had this behavior also with the log_to_file.
a simple restart of the iwl with ifconfig w1p1s0 down && ifconfig w1p1s0 up fix the issue of the broken driver.

i try to merge your code with the code by pgawlowicz.
Did the following function I found in your code work?

def read_bf_entry(self, data):
        """
            This function parses a CSI payload not associated with a file (for example: those extracted via netlink).
            Parameters:
                data (bytes): The total bytes returned by the kernel for a CSI frame.
            Returns:
                csi_block (dict): Individual parsed CSI block.
        """

        csi_header = struct.unpack("<LHHBBBBBbBBHH", data[4:25])
        all_data = [x[0] for x in struct.Struct(">B").iter_unpack(data[25:])]

        csi_block = self.read_bfee(csi_header, all_data)

        return csi_block

Because I get an exception if i want to fit the udp payload into this function
csi_header = struct.unpack("<LHHBBBBBbBBHH", data[4:25]) struct.error: unpack requires a buffer of 20 bytes.

the code diff at netlink.py is only:

CN_NETLINK_USERS = 11 #his
CN_NETLINK_USERS = 10 #yours

and the return of the payload :

payload = data        # his
payload = data[32:] #yours

it seems that if the CN_NETLINK_USERS = 10 is set, then the socket is never receiving datagramms. therefore i think the 11 is right. but which datapart has to be passed to the read_bf_entry? Both variants caused the same error

Here you can find the current code state:
https://github.com/tweigel-dev/CSIKit/tree/feature/realtime

with the following snipped you can try to use the realtime capture:

def print_and_fill(csiEntry):
    print(csiEntry)
    global entrys
    entrys.append(csiEntry)



reader = IWLBeamformReader()
entrys = []
reader.read_log(print_and_fill)

I noticed that data[4:25] gives a length of 21, but the struct.unpack needs 20. There is the source of the issue I think

Hi, that code is functional but incomplete. My only test system using IWL5300 encounters a buffer overflow after reading CSI in real-time for longer than 1 minute. I am inexperienced with Linux sockets and as such haven't been able to effectively debug this issue. For now there may be better solutions for this elsewhere, but I may be able to investigate this again soon.

Look here maybe this helps you to fix the issue
dhalperi/linux-80211n-csitool-supplementary#175

Gi-z commented

Thank you, I will attempt this solution once I've also had time to merge your PR!