Is it possible to estimate the arbitration time on MAC layer with linux kernel tracing? (ieee802.11, ath9k, ad hoc network) - linux

I want to measure the arbitration time on the MAC layer at runtime.
Setup: I have installed a patched Linux kernel with an ath9k driver. I have no tools other than my two computers to find out what I am looking for. Both exchange messages via a 5G ad hoc network, so nothing else between them. Moreover, both use ptpd via ethernet. I followed the instructions on https://wireless.wiki.kernel.org/en/users/drivers/ath9k/debug to enable debug mode. However, when I enter dmesg I am not sure I see more information than before. Additionally, retransmissions on the MAC layer are disabled.
Anyway, I found out that I cannot see what exactly happens on my Wifi adapter with my setup. But still, I want to get close, for instance, to see a tendency, rise, or fall of arbitration time. I had the idea to use kernel traces to get as close as possible to the MAC layer. Btw, if I have wrong assumptions, I appreciate any hint. I assume the messages pass the following layers (omitting the application here):
kernel (tx) UDP socket -> IP -> 80211a -> PHY -> 80211a -> IP -> UDP socket (rx) kernel
Current state: So far, I figured out with a little help of trace-cmd, ftrace, and the source code of ath9k that the closest I can get happens in functions of xmit and mac. In my traces I can see skb is consumed at one point and a DMA for the wifi device. From there, I suppose, it is up to my wifi adapter to do the arbitration and transmission. The next I can trace happens on the receiver kernel. There I can see something like an rx interrupt. So between those two measurements occur MAC layer operations and the physical transmission. Am I correct so far? Is it true that the duration on IP is negligible because there is no routing in ad hoc (A)? If so, I can measure the mac layer operations and transmission time so far, but I can not separate them from each other.
In the source code of ath9k are lots of other functions that did not appear in my traces like ath_tx_send_normal, ath_tx_complete. So I am wondering if I missed something in the ath9k debug tutorial. Is there a possibility at all of retrieving the information I am looking for (B)? If not, is it sufficient enough to calculate the physical transmission time and subtract it from the duration it takes from one kernel to the other (C)?
Besides, I would like to know how I can access strings that appear in functions like read_file_phy_err, ath_tx_complete, and the ath_dbg information (D).
I would really appreciate any hints to help me understand the processes on Linux kernel, ath9k, and 80211. If I could not make clear what I do, I will try to clarify. Thanks in advance.

Related

How to keep wifi link up when an embedded linux device suspends to RAM

Environment:
I have an embedded linux system running with an ARM based iMX7 processor. It runs on a build from yocto linux which is very much based on Fedora.
Scenario:
My system uses Suspend To RAM feature which is linux system power saving mode that is explained quite well in this link. This is done to save power at a certain stage.
Objective:
Now, I need to keep the wifi link open during this stage. And as I read from some discussions like this, it seems to be possible to do so.
How can I do this?
Read up on similar discussions:
Reading through this discussion, it explains how to do this on a intel based desktop linux computer. But I don't have the /etc/NetworkManager on my embedded linux device. Probably there is a different way to do it on a Fedora based embdded linux system.
Can I get some suggestions on how to do this or even how to approach this?
None of the articles you quoted even suggest that it is possible to leave WiFi on - in fact one of them says it can't be done. All they provide is various tricks to make the wake-up faster.
Depends on the hardware but very likely, leaving it on is really impossible. Suspend-to-ram includes a hardware command that switches the CPU clock off, places its interconnect buses into idle state, and disables main power to all the peripherals (leaving only standby power to those peripherals that support standby mode).
I don't know if your WiFi device has support for running on standby power nor whether the embedded hardware you have has the ability to provide that power to it while the CPU is off. If that ability exists, it will likely be accessible as a kernel driver parameter.
You may be able to save some startup time when waking up from standby by providing a static configuration for your WiFi device rather than using the default automatic connection (which involves searching for a router to connect to, obtaining an IP address, etc.).
You can't just keep wifi active during sleep/resume. You can optimise reconnection speed but I believe NM and connman both do that already.

how can we send/received frames in layer 2 (Using MAC address ) in Linux kernel

I am doing research in parallel computing side in my master. we are creating a real TriBA-Network a Triple based architecture (for multi core processor network). For this i am working on network part. So i have to implement routing in this network on layer 2 level. i have done routing on layer 3 (network layer) using TCP\IP protocol. But we have to send/received frames (not packets) on layer 2.
Maybe i can use RAW socket for sending frames using network programming. but how we can received these frames in remote PC and forward.
If somebody know about lower level communication that i can use for this task kindly share here.
Advance Thank you.
Computer's are connected in that topology over LAN locally TriBA Topology Network
From the question it's not that clear why this is to be done in kernel.
However, I understand from the question that some lower-layer approach is needed. If there are some explicit latency or throughput requirements then it needs to be stated in the question.
So, if we postpone the hypothetical in-kernel approach, indeed, you may use PF_PACKET sockets to send them. The same way, using PF_PACKET sockets you may receive them at the remote side. However, typically, this still involves certain overhead since the kernel copies data between its own buffers and the socket buffers accessed by the user in the userland.
From this perspective you may consider PACKET_MMAP technique to set up direct memory mapping to access data from kernel-side buffers. This might be a really good improvement in terms of, say, throughput, but it's rather controversial whether this will fit your need of forwarding.
Another one suggestion is to use some sort of like data plane kit (please find the link on that page) which may have a set of libraries designed specially for kernel-bypass networking (similar to PACKET_MMAP, but much better) and for certain tasks like L2 forwarding.
All in all, it is likely that you have enough tools to do what you need, however, a more detailed description would be better for understanding.

Linux - Nic's flags configuration

Context
Debian 64 bit. kernel 3.18.x
Litterally struggling to understand how a network driver is initialized.
I mean how to choose which flag to set. I dig in the kernel for days now to train myself. The card setup is the only point I miss.
I take the intel 82574 as an example. I downloaded the card's datasheet, saw many information but not a clue on how to setup the hardware.
Question
Where to start to know what flags to set ? The datasheet didn't helped me (i am not very experienced but willing to learn).
Please give me a starting point, a tip or anything to help me understand what is going on in the already written open sourced driver.
How can a developer knows how to initialize his nic ? (yes reinventing the wheel the time to understand)
You'll need to read the source code of the kernel module that handles your specific NIC.
EDIT: Of course, to develop such a module, you'd usually just use a register map as specified in a data sheet or application node; often, manufacturers develop their linux drivers themselves, so the driver developers might even be the same people that developed the chipset (because it's really handy to have a platform to test against -- it's impossible to test hardware without having something like a driver, so you might as well write a proper driver).
Furthermore, devices often come with code examples -- no one is going to build a device based on an IC that he has not seen in action.
If you've got access to neither proper documentation nor source, you can only reverse engineer - and that's an incredibly large field.
Using your example with the Intel 82574 Network Adapter, Intel provides a zip file of the source code used to build the Linux driver. The driver is like all drivers in that it hooks into the OS API for Networking.
The Linux networking API is document on both the linux.org site and discussed on popular Linux sites like lwn.org. Below is the link to lwn's chapter on Network drivers using the networking API called NAPI.
https://static.lwn.net/images/pdf/LDD3/ch17.pdf
You'll notice in the Intel igb driver source code that the NAPI net_device data structure is one of the first things that is setup. It registers the driver with the OS. This way the OS knows which igb functions to call when loading/unloading the driver, or when needing to send/receive data.
The igb functions read/modify/write the necessary bits in the 82574's memory-mapped registers that control and monitor the device. The device registers are all documented in the 82574 datasheet available on Intel's site. And this is usually the case for almost any networking company like Broadcom/Chelsio/Mellanox/Marvell.
Hope that helps a little more.

Accessing wireless interface (802.11) at MAC layer (Linux)

I spent the last days reading through man pages, documentations and anything else google brought up, but I suppose I'm even more confused now than I was at the beginning.
Here is what I want to do: I want to send and receive data packets with my own layer 3-x protocol(s) via a wireless interface (802.11) on Linux systems with C/C++.
So far, so good. I do not require beacons, association or any AP/SSID related stuff. However, for data transmissions I'd like the MAC layer to behave "as usual", meaning unicast packets are ACK'd, retransmissions, backoff etc. I'd also like to enjoy the extended QoS capabilites (802.11e with 4 queues and different access categories). Promiscuous mode on the other hand is not a concern, I require only broadcast packets and packets sent to the specific station.
What would be the right way to go about it? Most of the documentation out there on raw socket access seems to be focused on network sniffing and that does not help. I've been playing around with the monitor mode for some time now, but from what I've read so far, received packets are not ACK'd in monitor mode etc.
Without monitor mode, what would be the alternative? Using ad hoc mode and unix raw sockets? Or do I have to fiddle around with the drivers?
I'm not looking for a complete solution, just some good ideas, where to start. I read through the man pages for socket(2), socket(7) and packet(7) but that did not help concerning the behaviour of the MAC layer in different modes.
Thanks in advance.
802.11 is layer 2 (and 1) protocol specification. It was designed in a way, which allows higher-layer protocols to treat it as Ethernet network. Addressing and behaviour is generally the same. So for a layer 3 protocol you should not be concerned about 802.11 at all and write your code as if you were expecting it to run on Ethernet network.
To make it work you should first connect to a wireless network of some sort (which is conceptually equal to plugging a wire into a Ethernet card). Here you may choose ad-hoc (aka IBSS) or infrastructural (aka BSS) network (or PBSS once 802.11ad is approved ;).
Operating cards without any sort of association with network (just spitting out packets on air) is not a good idea for a couple of reasons. Most importantly it's very hardware dependent and unreliable. You can still do it using RF mon (AKA monitor mode) interface on one side and packet injection (using radiotap header) on the other but I don't recommend that. Even if you have a set of identical cards you'll most likely encounter hard to explain and random behaviour at some point. 802.11 NICs are just not designed for this kind of operation and keep different mount of state inside firmware (read about FullMAC vs. SoftMAC cards). Even SoftMAC cards differ significantly. For example theoretically in monitor mode, as you said, card should not ACK received packets. There are cards though that will ACK received frame anyway, because they base their decision exclusively on the fact that said frame is addressed to them. Some cards may even try to ACK all frames they see. Similar thing will happen with retransmissions: some cards will send injected packet only once (that's how it should work). In other NICs, retransmissions are handled by hardware (and firmware) and driver cannot turn it off, so you will get automatic retransmission even with injected data.
Sticking with layer 3 and using existing modes (like ad hoc), will give you all capabilities you want and more (QoS etc.). Ethernet frame that you send to interface will be "translated" by the kernel to 802.11 format with QoS mapping etc.
If you want to find out about MAC behaviour in various modes you'll have to either read the mac80211 code or 802.11 standard itself. http://linuxwireless.org wiki my help you with a few things, but kernel hackers are usually to busy to write documentation other than comments in the code ;)
L3 protocol implementation itself can be also done either in kernel or user mode (using raw sockets). As usual kernel-side will be harder to do, but more powerful.
Because you want to create own network layer protocol (replacement for IP), the keyword is: "raw ethernet socket". So ignore "Raw IP socket" stuff.
This is where to start:
int sockfd = socket( PF_PACKET, SOCK_RAW, htons(XXX) );
Correct man page is: packet(7).
Find more information by googling with the keyword.
One quite complete example here.
Edit: The link to the example seems to be currently broken: another examples
Probably you want something like libpcap.
Libpcap allows you to read/inject raw packets from/into a network interface.
First, there’s something you should be aware of when trying to transmit raw 802.12 frames- the device driver must support packet injection.
You mentioned monitor mode, which is at a high level the rx equivalent of the injection capability- which is not a “mode”, jist a capability/feature. I say this because some 892.11 device drivers on Linux either:
Support monitor mode and frame injection
Support monitor mode and not frame injection
Support neither
I don’t know any straightforward way to check if the driver supports frame injection aside from attempting frame injection and sniffing the air on another device to confirm it was seen.
Monitor mode is usually easy to check by using sudo wlan0 set monitor and seeing what the return code and/or output is.
It’s been a few years since I’ve worked on this but at the time, very few devices supported monitor mode and frame injection “out of the box”. Many only supported monitor mode with a modified version of the vendor or kernel driver
You’ll want to make sure your device has a driver available that fully supports both. This sort of task (frame monitoring and injection) is common for Penetration Testers who tend to use Kali Linux, which is really just an Ubuntu distribution with a bunch of “hacking” tools and (modified) 802.11 device drivers preloaded and in its repositories. You can often save time finding a well supported card by using a search engine to find the device and driver recommended for Kali users
I’m bringing this monitor/injection capability up explicitly because when I first worked on a similar project a few years ago, I needed to use a patched version of the official kernel driver to support monitor mode- it was an rtl8812au chipset. At that time, I made an incorrect assumption that monitor mode support in the driver implied full injection support. I spent 2 days banging my head against the wall, convinced my frames weren’t built correctly in my application, causing no frames to leave the card. Turned out I needed a more recent branch of the driver I was using to get the full injection support. This driver in particular supports both monitor mode and frame injection now. The most frustrating thing about diagnosing that problem was that I did not receive any errors from system calls or in kernel messages while trying to transmit the frames- they were just being silently discarded somewhere, presumably in the driver
To your main question about how to do this- the answer is almost certainly libpcap if you’re writing your application in C/C++ as libpcap provides not only packet capture APIs but also packet injection APIs
If you do it in Python, scapy is an excellent option. The benefit of Python/scapy is that
Python code is much quicker to write than C
scapy provides a significant amount of classes that you can use to intuitively create a frame layer by layer
Because the layers are implemented as classes, you can also extend and “register” existing classes to make certain frames easier to create (or parse when received)
You can do this in straight C using the UNIX sockets API with raw sockets directly- but you’ll have to deal with things that libpcap exists to abstract from you- like underlying system calls that may be required when doing raw frame transmission, aside from the standard socket(), send(), recv() calls. I’m speculating that there are a handful of ioctl calls you may need at the least, specific to the kernel 802.11x subsystem/framework- and these ioctl() calls and their values may not be completely portable across different major kernel versions. I’ll admit I ended up not using the pure C (without libpcap) approach, so I’m not 100% sure about this potential problem. It’s something you should look more into if you plan to do it without libpcap. I don’t recommend it unless you have a really good reason to
It sounds like you are getting the media and transport layers mixed up.
802.11 is what's commonly referred to as a "link", "physical", or "media" layer, meaning it only deals with the transmission of raw datagrams.
Concepts like ACKs, retransmissions, backoff (flow control) apply to the "transport" layer, and those particular terms are strongly associated with TCP/IP.
Implementing your own complete transport layer from scratch is very difficult and almost certainly not what you want to do. If instead you want to use the existing TCP/IP stack on top of your own custom interpretation of 802.11, then you probably want to create a virtual network interface. This would act as an intermediary between TCP/IP and the media layer.
Hopefully this gives you some better context and keywords to look for.

Hardware clock signals implementation in Linux Kernel

I am looking at some pointers for understanding how the Linux kernel implements the setting up of various hardware clocks. This basically relates to working with setting up the various clocks that hardware features like the LCD, UART etc will use. For example when Linux boots how does it handle setting up the clocks for UART or USB. Maybe something like a Clock manager or something.
I am basically trying to implement something similar for a different OS on a new hardware that i am working on. Any help would be really appreciated.
[Edit]
Thanks for the replies and the links. So here is what i have implemented up until now. This should give you an idea of where I'm headed.
I looked up the Hardware Reference Manual for the particular system I'm targeting and wrote some code to monitor/modify the signals/pins of the peripherals I am interested in i.e. turning them ON/OFF from the command line.Now a collection of these clocks/signals together control a peripheral.The HRM would say that if you want to turn on the UART or something then turn on such and such signals/pins. And #BjoernD yes I am using something like a mmap() function to talk to the peripherals.
The meat of my question is that I want to understand the design and implementation of a Clock/Peripheral Manager which uses the utility that I have already written. This Clock/Peripheral Manager would give me the control of enabling/disabling the peripherals I want.Basically this Manager would enable me to make changes in the init code that is right now running. Also during run time processes can call this Manager to turn ON/OFF the devices so that power consumption is optimized. It might not have made perfect sense but I'm myself trying to wrap my head around this.
Now I'm sure something like this would have been implemented in Linux or for that matter any OS for performance issues (nobody would want to waste power by turning on all peripherals at boot time). I want to understand the Software Architecture of it. Reference from any OS would do as of now to atleast get a headstart. Also I am not writing my own OS, there is an OS in place but Im looking more at a board level software aka BSP to work on. But thanks for the OS link anyways, they are really good. Appreciate it.
Thanks!
What you want to achieve is highly specific to a) the platform you are using and b) the device you want to use. For instance, on x86 there are 3 ways to communicate with a device:
Interrupts allow the device to signal the CPU. The OS usually provides mechanisms to register interrupt handlers - functions that are called upon occurrence of an interrupt. In Linux see request_irq() and friends in linux/include/interrupt.h
Memory-mapped I/O is physical memory of the device that the platform's BIOS makes available in the same way you also access plain physical memory - simply by writing to a memory address. What exactly is behind such memory (e.g., network interface config registers or an LCD frame buffer) depends on the device and is usually specified in the device's data sheet.
I/O ports are accessed through a special address space and special instructions (INB/OUTB & co.). Other than that they work similar to I/O memory.
There's a multitude of ways to find out what resources a device provies and where the BIOS mapped them. Some platforms use ACPI tables (google yourself for the 1,000k page spec), PCI provides info on devices in a standardized way through the PCI config space, USB has similar ways of discovering devices attached to the bus, and some devices, e.g., UARTS, are simply specified to be available at a pre-configured I/O range that is fixed for your platform.
As a start for understanding Linux, I'd recommend "Understanding the Linux kernel". For specifics on how Linux handles devices and what is there to write drivers, have a look at Linux Device Drivers. Furthermore, you will need to have a look at the peculiarities of your platform and the device you want to drive.
If you want to start an own OS, a UART is certainly something that will be veeery helpful to print debug output, so you might want to go for this first.
Now that I wrote down all this, it seems that your actual question is: How to get started with Operating System design. This question should be highly valuable for you: What are some resources for getting started in operating system development?
The two big power users in most computers are the CPU and the disks. Both of these have capabilities for power saving in Linux. The CPU clock can be slowed down when the system is not busy, and the disk motors can be stopped when no I/O is happening. For a UART, even if you save all of the power that it uses by turning off its clock, it is still tiny compared to the others because a UART doesn't have much logic in it.
Best ways to save power are
1) more efficient power supply
2) replace rotating disk with SSD
3) Slow down the CPU and memory bus

Resources