GSoC 2024: New release for Project Libremesh Pirania – Part II

Hello! This post is about my progress so far while working on the new release of Pirania package for the new version of LibreMesh 2024.1 which runs on top of OpenWrt 23.5.3.

During last month there was a lot of interaction with the community via mailing lists and Matrix chat room.

Goals of this project

Pirania is a captive portal designed for community networks. It allows community members to create vouchers (or tickets ) in order to manage access to the internet. When a device access the network for the first time it redirects for the captive portal. Then, it’s needed to insert the voucher previously create by a community operator.

This promotes the sustainability of the network, since there’s costs involved in maintaining one.

What needs to be done

In version 22.03 of OpenWrt the new framework for packet processing and firewall was change from iptables (firewall3) to nftables (firewall4). Since Pirania captive portal uses iptables rules to redirect and allow/deny traffic from clients, there is a need to also update the rules that are created by captive-portal script.

First try

Here i will discuss what worked and what’s not.

Since i have a compatible router with Lime old version 2020.4, a TP-Link Archer c50 v1, i wanted to flash it and see Pirania functionalities in practice. Downloaded a pre-compiled firmware and flashed. It worked and the next step was to install Pirania and start it.

I got some errors (in feeds, while running “opkg update”, more specifically) while installing Pirania which i reported in Matrix chat. Community members helped me and confirmed that this error was not present in recent versions.

Error:

Collected errors:
opkg_download: Failed to download http://downloads.openwrt.org/releases/19.07.10/packages/mipsel_24kc/libremesh/Packages.gz, wget returned 8.
opkg_download: Failed to download http://downloads.openwrt.org/releases/19.07.10/packages/mipsel_24kc/profiles/Packages.gz, wget returned 8.

If you run into error during update and install process of Pirania, do the following:

“it should be enough to delete the libremesh and profiles rows in /etc/opkg/distfeeds.conf as the correct info should be already present in /etc/opkg/limefeeds.conf”

After changing this files, i was able to install Pirania package. But, forgot to install ip6tables-mod-nat and ipset, then my router entered in a weird state. Moving on..

Second try

One of the last GSoC there was a project that aim on easing the virtualization of LibreMesh. Available here. But since the contributor has not changed the requested modifications, it is still open the issue.

I was able to virtualize both Lime 2020.1 and 2024.1 versions. I used the scripts available in lime-packages/tools in order to emulate with Qemu software. Unfortunately wasn’t able to provide internet access to the node itself.

Third try

I had a Rocket M5 MX standing idle and decided to flash with latest version of LibreMesh on it. The installation was easy and is working fine. Just had to add the following line to /etc/config/lime-node in order to get a valid IP from my local network since it only have one physical interface, in order to install ipset package.              

config lime network
config net portwan                                       
      option linux_name ‘eth0’                      
      list protocols ‘wan’   

Then, i was able to install the dependencies necessary to test my code.

Workflow

It’s really easy to test new software in Libremesh, since are usually scripts that need to be modified and can be run at run time. Just modify and upload the script to the working node and you are ready to go.

Code so far

I’m currently working on this branch, which link is below:

https://github.com/henmohr/lime-packages/blob/mohr-patch-nftables-1/packages/pirania/files/usr/bin/captive-portal

Next steps

The next step is to upload this script to a running node and see what happens.

There is a need to add more comments on the code and also with nftables is possible to enable remote logging of each rule that is executed, so will help a lot on debugging this script.

Also, i managed to setup a working node using VirtualBox. Maybe an alternative would be to create a VM with some Linux distribution and then connect it to the LibreMesh node, easing the process of testing.

GSoC 2024: Visualise community data, update 1

I’ve set up a lot of services since planning out the data pipeline in June; the new infrastructure diagram looks like this:

So, I wrote a little Rust utility called json_adder which takes the JSON files and reads the data into a MongoDB collection. We also have a GraphQL server, running through Node.js, which can handle some (very) simple queries and return data. Many of these services are individually easy to set up, the tricky part is making sure everything works together correctly. This is what your favourite technical consultancies call “fullstack development”.

Data loading

The first change from the initial plan was to use MongoDB instead of MySQL as a database. MongoDB has a built-in feature for handling time-series data, which is what we’re working with. It integrates well enough with GraphQL, and since one of my mentors (Andi Bräu) works with MongoDB on a daily basis, there’s a lot of experience to draw upon.

Here is the Rust code for the utility which adds the data to the database, and here’s what it does:

  • Read over each JSON file in the directory in a loop.
  • Extract the last-modified time from each community in the file and do some conversion to BSON.
  • Read the data into a struct, and add each object to a vector.
  • Insert the vector into the MongoDB collection.
  • GOTO next file.

When setting up the connection to MongoDB, the setup_db module will also check to create the collection if it doesn’t exist. This extra bit of logic is ready for when this has to be run in an automated process, which might involve setting up the database and filling it with data in one go.

I don’t have a binary to link here, and will write build instructions in future.1 On each commit which changes Rust code, Github Actions runs cargo check on the repository. When it comes to deploying this in reality, we can change that workflow to provide release builds.

At the moment it is a one-way process. You point json_adder at the data directory and it adds everything to the database. For future work, I’ll need a way to keep the database in sync, only add the files which have been modified, run it on a schedule. For now, it works fine.

GraphQL

Here is the GraphQL server code. Fetch the dependencies, in this order:

npm install express express-graphql graphql mongodb

The ordering of these is important.

Then, run npm start, and open http://localhost:4000/api in your browser, you should see the GraphQL IDE.

At the moment, the GraphQL can handle a query with an argument for metadata. I’ll build out the schema, and the resolver, to handle more arguments / more complicated queries. A lot of the documentation for GraphQL assumes a fairly simple schema, built for handling calls to a web app, which is slightly different from our case. The JSON Schema for the Freifunk API is not only quite long, it is also versioned, and newer versions are not necessarily backwards-compatible. I am going to sidestep this complexity by writing a GraphQL schema which only includes fields available in all versions. My first working example to try is a query which counts the number of nodes per community.

You’ll notice that the last step in in the pipeline is yet to be completed, I don’t have a visualisation to show. But, now that we can reliably pull data all the way through the pipeline, we’re almost ready to make some graphs.

  1. In the meantime, you only need to run cargo build in the json_adder directory. ↩︎

GSoC 2024: LibreMesh Cable Purpose Autodetection Update

Hello everyone! This blog post is meant as a mid-point update on the Cable Purpose Autodetection project.

This first part of the project was the occasion for a lot of discussions on how the project will take place to occur, and discuss how it will materialize for a LibreMesh user. These discussions mostly happened in the LibreMesh mailing list, and in the public matrix channel.

What is the goal of the project again?

In some scenarios, routers running LibreMesh benefit greatly from having specific configurations applied, which are not yet natively integrated — As of now, an expert needs to step in and setup these configurations manually, which is not always an option for communities. For this project, I am investigating scenarios that would benefit from automatically applied configurations.

What was discussed

There was a lot of discussions in the LibreMesh mailing list and in private messages, talking about the implementation and the scope of the project

Here is a sample of configurations where it would be useful to have such a system:

  • A LibreMesh router is connected to the internet and is serving internet access to its clients.
  • A LibreMesh router is connected using Ethernet to another LibreMesh router in the same network, to extend coverage.
  • A LibreMesh router is connected to another router not running LibreMesh, but working as an access point (in a point-to-point link) for client connecting to that router, and transferring data to the LibreMesh router.

Multiple solutions where discussed in the mailing list, for example, it would be useful to detect if a neighbor router is running LibreMesh or another firmware. A solution consisting of LibreMesh having its own ipv6 multicast has been discussed. This would allow a LibreMesh-running router to be more aware of what is around itself, and it could also detect if another LibreMesh router is part of the same network or a different one.

Implementation Solutions

One main point of discussion was “how to apply the configurations”. There was a lot of back-and-forth on that subject. The final software would take the shape of multiple scripts, each dedicated to tackle a single configuration setting.

  • The configuration scripts could be ran automatically at runtime. For example, a script could run every time an interface goes up or down. This means that if a link between two routers is broken, and somehow goes on and offline regularly, the configuration setting would be applied repeatedly, and in the process, could break some other part of the configuration. In that situation, potential problems would be very hard to troubleshoot if the user is not warned that this auto-configuration is occurring.
  • The configuration scripts could be ran when the user runs “lime-config”, which is an existing configuration tool for LibreMesh. This would avoid the problem of a script running repeatedly, because the user would stay in control, but it kind of ruins the whole “running configurations automatically” aspect of the project.
  • Another solution would be to implement buttons & switches in the Lime-app (that currently allows you to manage a node and its network), and add a new page or field where a user could choose if a specific configuration should be automatically applied, apply it manually or not at all. The problem is that the name of these settings might be obscure to less tech-savvy users.

So, we have different possibilities, each with their advantages and drawbacks. The solution will be to have some auto-configuration applied in a way, and other auto-configurations applied in another way.

Virtualization and problems encountered

One of my biggest roadblock in starting this project was running virtualization software. A previous Google Summer of Code participant made modifications to the LibreMesh code to allow virtualization using Qemu or Ansible (available here), but this code wasn’t pulled into the LibreMesh repository because it is not fully ready yet. This implementations contains instructions and modifications that allows LibreMesh to virtualize with Qemu and Ansible, and both of those software have different working and breaking points, and I had to experiment a lot to learn how to solve or work around them.
Using Qemu, it is possible to run up to 100 routers that act as nodes in a network. You can access each node using ssh to ping, create interfaces or check connection from one to the other.
Using Ansible, you can use the qemu_cloud_start.yml file to pre-configure and fine-tune the layout of your network before starting the virtualization in batches. (This makes it easier to specify which node should be an edge node, connected to the network, etc…). This .yml file is working as a blueprint for Ansible, and it will build your interfaces and network of nodes from the instructions contained. You can then run the nodes as a single batch, and connect to each of them using ssh.

However, virtualization is limiting when trying to understand a system. Simulating the cables connecting each node of a network is harder to visualize, in lieu of plugging everything by hand, and you often encounter problems that would not happen if you were working on actual hardware.
For example, connecting the virtual machine to the Internet is challenging (and not working 100% of the time), because you need libraries that are not checked from starting the virtual machine software, and the error messages you get from the machine are not clearly related to what the actual problem is.

Alternative: Working on actual hardware

I am currently waiting to receive a few routers that a community member (Aparcar) sent to me. I plan on using these routers to setup a LibreMesh network, and implement the changes I made in a more physical way than my current virtualization setups.
This setup will allow me to bypass some of the problems I am regularly encountering specifically because of the virtualization, at the cost of a slower iteration cycle. I’m looking forward to setting up and tinkering with actual hardware!

Next steps

  • The biggest next step is implementing code that can actually detect the specified configurations. The foundation for this is done, but more work is needed to make code that can fit the use cases.
  • From the mailing list, a lot of different solutions were discussed. We seemingly have more solutions than problems, so the next steps are implementing some of those solutions, seeing how they fit together with the current LibreMesh code, and choosing which are the best candidates to solve the auto-configuration problems.
  • Another big next step is transferring my changes to an actual router running LibreMesh code, to be able to test and code in a real-world setting

Bonus learning material

Q&A video

A big help in this project was a Questions & Answers session we organized with seasoned LibreMesh developer. We recorded the session, thinking that it would be good to keep track of some ‘newbie questions’ and their answers, for future onboarding. I uploaded the video to guifi-net’s peertube, using LibreMesh’s account. Thanks again to everyone who participated!
The video is available here

Vocabulary list of technologies

Another help in my learning process was a vocabulary list of the technologies I learned of, and how they were used within LibreMesh. This list gets extended every time I lean about a new part of a technology.
There was a lot more abbreviations I had to learn than I anticipated, and I’m still encountering more new ones every time!

Closing words

And that’s about it for a mid-project update! Thank you for reading, and don’t hesitate to send me a message if you’d like to know more.

GSoC 2024 Qaul: Qaul BLE module for Linux: Part-II

This post is a continuation of my last one, which discussed the theory behind Qaul BLE support for Linux where I explained the theoretical concepts and jargon and high-level system design for Bluetooth low energy flow using GATT. Please refer to that blog before proceeding.

In this blog, we will explore the implementation and low-level design of the BLE support in greater depth.

Introduction

We will begin with creating a GATT server serving two Bluetooth services “main_service” and “msg_service” with their respective UUIDs and characteristics for our qaul device. Then we will use the adapter to advertise the “main_service_uuid” for another qaul device to connect to the GATT server. Afterward, we will create a GATT client by starting a scanning service to discover nearby advertisements. The last thing to do is to set a few functionalities and callbacks like read and write characteristic data methods and request_read and request_write callbacks for characteristics to set a basic GATT prototype with message transfer support.

GATT Server

If you remember the GATT data hierarchy diagram from the last blog shows the GATT server is made up of services and each service is made up of characteristics and each characteristic of descriptors. Here, we will dive into details of how to implement it using BlueR.

GATT Service: GATT services are a set of similar attributes in one common section of the GATT server. For Qaul GATT Server implementation, we have two services – mainService, and msgService and their UUIDs (99xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx23). Below is a struct for Service where you specify uuid, characteristics and whether the service is primary or secondary.

GATT Characteristics: Characteristics are the containers for user data. For the Qaul Gatt Server, we have one characteristic for each service ➖ mainChar, msgChar, and their UUIDs with respective configurations. You can specify the uuid, descriptors(if any), read permission, and callbacks under the read attribute, and write permissions and conditions under the write attribute.

Now, you can create a new session to get an instance of your Bluetooth adapter and start the service GATT application using the above configurations. Below is a sample example of a GATT server with read characteristics functionality enabled.

Advertisements and Device discovery

We will use the above instance of the adapter to start advertising the main_service_uuid to be discovered by other devices. (Refer to sample code).

We can start scanning for nearby devices advertising the same UUID for the presence of qaul. For this, BlueR gives us adapter.set_discovery_filter(get_filter()).await; a feature for filter-based UUID scanning. and stream the discovered device adapter.discover_devices().await.

Till now we have created a Ble GATT server and client, the next thing we will implement is confirming the discovered devices for a qaul node, maintaining a list of discovered devices to save the throughput of scanning devices again and again, and keeping track of devices out of range.

For Qaul ble architecture, we have stored the qaul_id in the main_service’s characteristics, Now, whenever any device discovers this node, it will connect to it, check for the presence of both services along with their characteristics, and mark that qaul_id as discoverable. If the conditions are satisfied, it adds the node and its properties to a lookup map. To keep track of the device’s availability after discovery, Qaul spawns a new task out_of_range_checker to ping recently discovered devices at regular intervals to confirm their presence.

Any message to be sent can be written into msg_service’s characteristics using CharacteristicWriteMethod::Io and receive any write request using CharacteristicControlEvent::Write(write). The message read and write process is a bit more complex than function calls. We will discuss it in more depth in the next blog.

So, in the current blog, we are able to create a GATT server and a GATT client, advertise our UUIDs, and scan for nearby BLE devices. We also learned to identify the correct device and maintain the lookup table for better connectivity and more stability.

Concluding Thoughts

The first half of the GSoC coding period had more code implementation for ble connectivity. The major part was into integrating the prototype to work with async rust on multiple threads. The next half will be implementing loss-less transmission of data and experimenting with bluer for better stability. If you want to know more about my project, please feel free to reach out. Thanks for reading!

Progress Update on GSoC 2024 Project: Throughput-based Dynamic WiFi Power Control for Real Networks

Hello everyone! With the first evaluation of GSoC 2024 approaching, I am sharing this blog post to give a comprehensive update on the progress of the Throughput-based dynamic Power Control Approach. Please check out my initial blog post for more information in case you need to become more familiar with WiFi power control. 

New Developments

1. Basic Python Package Creation

A basic Python package for the power control algorithm was successfully created. Let’s refer to this package as ‘power_controller’. The power controller includes a main class and exposes two primary functions: ‘configure’ and ‘run’.

The ‘configure’ function is designed to facilitate the setup of the Transmit Power Control (TPC). It allows for manual activation of the Transmit Power Control (TPC) mode. It initializes the modes of allowed power and parses the incoming control parameters. These parsed parameters are then returned to the ‘run’ function to execute the main logic.

The ‘run’ function implements the core logic of the power controller. This function is responsible for dynamically adjusting the transmission power at configurable intervals. It supports various power selections ensuring the power control algorithm can adapt to different network conditions in real time.

2. Integration with Python-WiFi-Manager

The power_controller has been connected with the existing Python-WiFi-Manager package from SupraCoNex. The WiFi-Manager package provides an interface to monitor each transmitted frame and control the transmission rate and power.

We utilize this interface by linking the power_control package and exposing the  ‘configure’ and ‘run’ functions for the WiFi-manager package for further power control. 

3. Development of Power Controller Logic

The ‘run’ command now includes a simple yet effective power controller logic. Key features of this logic are:

a) Configurable Update Interval: A customizable update interval has been added, allowing the system to adjust transmission power at defined intervals.

b) Dynamic Power Selection: At each update interval, a random supported power level is set as the transmission power which helps in dynamically exploring different power settings.

4. Power Setting Modes

Talking about dynamic power selection, various modes of power setting are introduced. These modes define how the transmission power is selected during each update interval:

  1. Highest: Always selects the highest supported power level.
  2. Lowest: Always selects the lowest supported power level.
  3. Random: Selects a random power level from the supported range.
  4. Round Robin: Cycles through the supported power levels in a round-robin manner.
  5. Fixed: Uses a predefined, fixed power level for all intervals.

5. Experimentation and Observation

A settings file was created to run the power controller with different power modes using the Experimentation Python package from SupraCoNex. The observations from the trace files were promising

  • Power Control Verification: It was confirmed that the power levels were being dynamically controlled as per the logic defined.
  • Rate Adaptation: The packet transmission rate was observed to change and adapt in response to the varying power levels, demonstrating the algorithm’s effectiveness in real-time conditions.

Next Steps

The next phase of the project will focus on advancement of the power_controller as well as data analysis and visualization to gain deeper insights into the performance of the developed power control algorithm. We will also advance the power_controller package.

Here is the outline:

1. Advancement of Power Controller

The major step would be extracting real-time throughput information for the power controller. Another step will be to implement the strategy to lower transmit power when the transmission is optimal. If in case transmission fails in this low power transmission, we stratetigize a method to fallback to higher transmission again.

2. Data Extraction and Plotting

  • Data Collection: Write a Python script to extract data on rate-time and power-time relationships from the trace files generated during the experimentation phase.
  • Visualization Setup: Utilization of visualization libraries such as ‘’matplotlib’ or ‘seaborn’ to create plots that can illustrate:
    1. Rate vs Power Selection Over Time: Plot how the selected transmission rate varies with different power levels over time.
    2. Throughput Analysis: Visualize throughput variations based on the chosen power settings and rate adaptations.
    3. Frame Aggregation: Analyze frame aggregation patterns and efficiencies under different power control strategies.

3. Analysis and Insights

Graphical Analysis: Interpret the plotted graphs to derive insights into:

a. Optimal Power Settings: Identify trends where certain power levels consistently lead to higher transmission rates and better throughput.

b. Impact of Rate Adaption: Understand how dynamic rate adjustments influence overall network performance.

c. Efficiency of Frame Aggregation: Evaluate the effectiveness of frame aggregation techniques in optimizing data transmission.

Based on this analysis, we can further iterate the power control algorithm to fine-tune parameters and enhance performance.

Conclusion

With the successful creation of the Python package, integration with SupraCoNex tools, and promising initial experiments, the second half of the coding period will be focused on power control in a real changing environment through data analysis and visualization. Please feel free to reach out to me if you would like to know more about the ongoing project. Thank you for reading. 

GSoC 2024: Visualise community data

Hello everyone, I’m Pierre, I was first introduced to Freifunk when searching for free WiFi in a cafe in Berlin, and I’m inspired by the radical visions of people attaching antennas to apartment buildings. Now I’m here to work on the community data API.

Since 2014, Freifunk has been collecting a snapshot of information about all communities, every hour, in a big directory available here. At the moment the data is being used for a calendar, a news feed,1 and a map of communities, among other services. Maybe you can think of lots of other things which could be done with that data, but first you would have to parse some 80,000+ compressed JSON files.

The goal of this Summer of Code project is to overcome that hurdle up front; make this community data more easily accessible, and uncover some insights about the network along the way. This is a typical situation for large archives, where one of the key challenges is making data readable and useful.

I intend to build a pipeline from the JSON directory through to some visualisations on a web page. One step behind that, I want to expose a GraphQL interface so that anyone else can query the data for their own purposes. The main part of this project revolves around setting up infrastructure to handle each section of this pipeline.

Although this system is conceptually very simple, there are lots of moving parts involved. The JSON files are loaded into a SQL database, the database talks to GraphQL, which itself talks to some browser-based visualisation library.

I’ve tried to make choices which prioritise boring technologies, reduce the fragility of this process, and hopefully make it easy to maintain in future. I will build it from the top down; starting with the database, and finishing with the visualisations themselves.

I’ll be working in this repository. There’s not much to show at the moment, but it should rapidly take shape in the coming weeks. My next post will be about the process of loading these files into a database.

  1. On which this blog appears, hello! 👋 ↩︎

GSoC 2024: New Transmit Power Control Approach for IEEE 802.11ax Wifi chips

1. Introduction

Hi everyone. I am Raul Shahi. I am currently pursuing a Master’s degree in Computer Engineering for IoT Systems from Nordhausen University of Applied Sciences, Nordhausen, Germany. For the past couple of months, I have undertaken the position of Research Assistant at my university, which involves researching and developing open-source software for IEEE 802.11 resource allocation.

For GSoC 2024, I will work on a novel Power Control algorithm to reduce interference and increase aggregate network throughput. This introductory blog post intends to summarize the necessary background to understand the details of the project.

2. Leveraging TPC performance for enhanced WiFi Performance

Regarding WiFi networks, ensuring everything runs smoothly is all about how we manage the available resources. As the concept of WiFi resource allocation has been covered by Prashiddha during his GSoC projects before, I would suggest the readers refer to his blog posts [3][4]. For IEEE 802.11 devices, deep diving into the system internals is required which can be overwhelming for developers as they would have to be familiar with kernel subsystems and Ansi C. This technical barrier makes it tough to adapt and innovate with new algorithms.

On top of that, many of the latest WiFi chips are becoming closed-source which means the open-source community can have a harder time developing new and advanced algorithms. However, chips like Mediatek, still share throughput information which can be utilized for the optimization of WiFi networks.

Active Transmit Power Control (TPC) is an exciting development area. By adjusting the transmit power for different devices, TPC algorithm extensions like Minstrel-Blues which is built on top of the Minstrel rate control algorithm are promising. They can reduce interference, boost overall network throughput, and improve how the network handles multiple devices in crowded spaces.

3. Motivation

To solve the challenges in WiFi resource allocation, the SupraCoNex project introduced the user-space WiFi Parameter Control API and an interface called Python-WiFi-Manger to enable the development of algorithms using Python. Developers can use these tools to create and test their algorithms on real WiFi chips. On top of the API, a remote socket extension has been realized to facilitate the remote management of access points. The API allows users to monitor transmission data and adjust rates and power on access points without technical knowledge of the kernel. 

I propose developing a new transmit power control algorithm using the WiFi-Manager for IEEE 802.11 ac chips, based on throughput estimates. This approach could potentially extend to Mediatek ax chips, paving the way for smarter, more efficient WiFi networks. However, the approach can be easily extended to any chips that expose the estimated throughput information and provide an interface to fine-tune power settings in real-time.

4. Methodology

The WiFi-Manager package in Python allows the user to monitor each transmitted frame while leveraging the options to control the rate and power for each connected access point. The first task will be to create a new Python package for the power controller and integrate it with WiFi-Manager. Since WiFi-Manager does not yet include throughput information, we will either add it to WiFi-Manager for broader use or directly into the power controller.

The power controller will track throughput at different power levels and average these observations using techniques like the Butterworth filter on EWMA. This can be the basis for determining the optimal transmission power. If throughput suddenly drops, the controller will have a fallback strategy, such as increasing power aggressively to restore the link quickly.

Like the Minstrel-HT [1] and Minstrel-Blues [2] algorithms, our power controller will have update and sample intervals. At the end of each update interval, it will adjust the power level based on recent observations. During sample intervals, it will explore different power levels to find the best settings.

The existing solutions from the Experimentation Python package from SupraConeX can be used to compare the proposed approach, evaluating performance based on rate selection, aggregation, throughput, and power levels.

5. Deliverables of The Project

The end goals of my GSoC 2024 project are as follows:

a. Implementation of a dynamic power control algorithm to adjust power levels
based on throughput information with the ready-to-run demo.


b. A detailed report documenting the research methodology, experimental setup,
results, analysis, and conclusions drawn from the study.


c. A study conducted using the Experimentation Python package that compares
the performance of the proposed approach with the existing solutions on
productive Freifunk Mesh and Access deployments.

6. What has been done until now?

a. Developed a foundational understanding of the importance of resource allocation in wireless transmission.

b. Familiarization with the ‘WiFi-Manager’ package as well as other packages from ‘SupraConeX’.

c. Remote access point setup for monitoring of data transmission and power, rate control.

7. What’s next?

a. Create a Python package for the power controller.

b. Preliminary performance comparison and evaluation of the developed algorithm.

8. Conclusion

I am incredibly grateful to be part of GSoC 2024 as we embark on this exciting journey. Developing and implementing a new power control algorithm with WiFi-Manager is just the beginning, and I am thrilled to contribute to innovations that could significantly improve WiFi performance. This project promises to push the boundaries of what’s possible in wireless communication, and I look forward to sharing our progress and successes with you. 

Please feel free to reach out and connect with me.

References

[1] Minstrel-HT Source Code in the Linux Kernel 

[2] A Measurement-Based Joint Power and Rate Controller for IEEE 802.11 Networks

[3] Minstrel TX Rate Control in User Space, Prashiddha, GSoC ‘22

[4] GSoC ‘22 and ‘23 blog posts from Prashiddha

GSoC 2024: Development of a Modular Assistant for OpenWrt

Hi everyone, I am Gabriel, and I am currently studying Web Application Development and Mobile Application Development. This summer, I will be participating in Google Summer of Code 2024 to work on developing a Modular Assistant for OpenWrt.

Abstract

The goal of this project is to develop a modular assistant for OpenWrt that simplifies the initial configuration of OpenWrt devices. This assistant will enable users to configure their devices quickly and easily, even without deep knowledge of wireless routers. The assistant will be implemented using LuCI, a framework for creating web interfaces for configuration and monitoring.

Plan Of Action

This project will focus on creating an assistant that guides users through the initial configuration of OpenWrt devices. The assistant will have a modular design, allowing it to be adapted to different scenarios and specific needs of communities like Freifunk.

Implementation

  1. Analysis of LuCI’s Client-Side API:
    • Understanding the operation of LuCI’s client-side API will be fundamental for the development of the assistant.
  2. Development of rpcd Services:
    • Learn how to write rpcd services for communication between the user interface and the backend of the OpenWrt system.
  3. Configuration of Permissions and Menu Entries:
    • Configure permissions and menu entries to ensure an intuitive user interface that is easy to navigate.
  4. Adaptable Modular Implementation:
    • Develop the assistant in a modular manner, allowing it to be adapted to different scenarios through scripts.

Deliverables

  • Creation of a stable, working modular assistant for OpenWrt.
  • Detailed documentation explaining the implementation and use of the assistant.
  • Ensure the assistant is adaptable for different scenarios and needs of the Freifunk community.

Concluding

I am delighted to be part of the GSoC 2024 program and contribute to the Freifunk project. I’m looking forward to collaborating with the Freifunk team to create a valuable tool for the community.

I would like to thank my mentors, Martin and Tobias, for their guidance and support. I hope to have a productive and successful summer working on this project.

GSoC 2024: New release for Project Libremesh Pirania.

Hi!

Very happy to be in this project. Piranha captive portal solves a well-known problem in community networks: the ability to manage vouchers and access to the internet and local services. As it says in it’s README:

It could be used in a community that wants to share an Internet connection and for that the user’s pay a fraction each, but needs the payment from everyone. So the vouchers allows to control the payments via the control of the access to Internet.

My name is Henrique and I’m currently working as a substitute teacher. My background is system administration and computer networks, so developing this project will be really challenging but I feel very comfortable doing so.

I’m also part of Coolab, a collaborative laboratory that fosters communities networks in Brazil.

Context

This project aims to develop the new release of Piranha, a package from Libremesh that enables communities networks to setup a captive portal and control/share internet access in a sustainable way. Currently Piranha is only supported in OpenWRT version 19.07.

The following are objectives of this project:

  • Migrate from iptables to nftables;
  • Include Piranha package on OpenWRT repository
  • Make necessary changes to work with DSA on newer routers

The use of captive portals in communities enables the creation of vouchers and parental control, for example, it’s possible to disable access to social networks during night time. Since community networks can have multiple gateways to the internet, there’s a need to share information about current vouchers. This problem is solved by the shared-state package. Below is an illustration of a home user setup and a community network setup:

Regular internet access

Community network internet access with multiple gateways

Acknowledgment

I would like to thanks Hiure and Illario from being my mentors on this project. Libremesh is an awesome project that enables non-technical people to deploy a mesh network in a matter of seconds.

Conclusion

I’ve never developed or upgraded a package before, i’m more into system administration, so it will be really challenging. 🙂

Thanks for reading and see you in the next post! Happy coding!

GSoC 2024: eBPF performance optimizations for a new OpenWrt Firewall

Introduction

Hello everybody! My name is Til, and I am currently a Master’s engineering student at the University of Applied Sciences Nordhausen. For the past year, I focused on Linux network programming, especially eBPF, which brings me to my GSoC 2024 topic.

Over the years, the network stack has evolved to support new protocols and features. The side effect is that this introduces overhead and might hinder network throughput, especially on CPU-limited devices. One solution to overcome this is eBPF.

eBPF and its hooks

eBPF (extended Berkeley Packet Filter) is a technology within the Linux kernel that allows to dynamically re-program the kernel without recompiling or restarting it. Developers can write programs in C code, compile them to BPF objects, and attach them to several so-called hooks inside the Linux kernel. You can use two hooks to redirect incoming data packages to other NICs inside the Linux network stack: XDP and TC.

The XDP (eXpress Data Path) hook is located even before the network stack itself; its programs are attached to the driver of the NIC. That should make it the fastest eBPF hook throughput-wise for redirecting packages.
But there is a catch: NIC drivers must support this so-called “XDP native” mode. Otherwise, you need to attach them through the so-called “XDP generic” mode inside the network stack, which is significantly slower than native, which you will see soon in this post.

The TC (Traffic Control) eBPF hook is already located inside the Linux network stack but is driver-independent, so only the Linux Kernel needs to support it, i.e., compiled with the respective symbol enabled.

My GSoC 2024 project

My GSoC 2024 topic/goal is to introduce a new firewall software offloading variant to OpenWrt using eBPF. The idea is to intercept an incoming data packet from the NIC as early as possible inside or even before the network stack through XDP or TC. Then, for the actual firewall part, apply possible NAT (Network Address Translation) and drop or redirect the intercepted package to another network interface. That saves some CPU cycles and hopefully increases the network throughput on CPU-limited devices.

There are mainly three parts that need to be designed and implemented:

  • The eBPF program which intercepts, modifies, and redirects or drops network packages
  • A user-space program that attaches the eBPF program to the NIC(s) and checks the actual firewall rules
  • A BPF map used for the communication between the BPF and the user-space program

The caveat of XDP generic

As mentioned, you can use the XDP generic mode if your NIC doesn’t support XDP native. Theoretically, the XDP generic mode should be faster than TC because the XDP generic hook still comes before the TC hook. But there is a problem: For XDP generic, the Linux kernel has already allocated the SKB for the network package, and XDP programs must have a package headroom of 256 Bytes. That means if the pre-allocated SKB doesn’t have a sufficient headroom of 256 Bytes, it gets expanded, which involves copy operations that effectively negate the actual performance gain.

I created a patch that, rather than making this package headroom value constant, creates a Linux kernel variable for that headroom exposed through the sysfs interface to Linux user space. It still has the default value of 256 Bytes, but then the user can explicitly lower the XDP generic package headroom according to his requirements.

The following table presents the head of a report generated by the Linux tool perf after running an iperf3 TCP test for 30 seconds through an MIPS router. I tested using an XDP generic package headroom of 256 Bytes first and then 32 Bytes. It shows how much CPU cycles this copy operation wastes.

26.91% ksoftirqd/0  __raw_copy_to_user
3.73%  ksoftirqd/0  __netif_receive_skb_core.constprop.0
3.04%  ksoftirqd/0  bpf_prog_3b0d72111862cc6a_ipv4_forward_func
2.52%  ksoftirqd/0  __kmem_cache_alloc_node
2.32%  ksoftirqd/0  do_xdp_generic
2.06%  ksoftirqd/0  __qdisc_run
1.99%  ksoftirqd/0  bpf_prog_run_generic_xdp
5.70%  ksoftirqd/0  bpf_prog_3b0d72111862cc6a_ipv4_forward_func
5.23%  ksoftirqd/0  __netif_receive_skb_core.constprop.0
3.68%  ksoftirqd/0  do_xdp_generic
3.02%  ksoftirqd/0  __qdisc_run
3.00%  ksoftirqd/0  bpf_prog_run_generic_xdp

I will tidy up and try to submit that patch to the upstream Linux Kernel. Some people also tried similar approaches to fix the XDP generic performance by reducing the package headroom constant but never got accepted. So I hope my different approach has more success.

What to expect throughput-wise

To get some impression about the performance potential of eBPF, I have created a little BPF program that forwards all incoming IPv4 network packages. To test the program, I used an AVM FRITZ!Box 7360 v2 running OpenWrt with Linux Kernel version 6.6.30, whose CPU limits the throughput performance of its Gigabit ports. Then I grabbed a PC with two network ports, connected both ports with one port of the FritzBox respectively, and created two network namespaces at the PC to force the network traffic through the FritzBox. I used iperf3 to generate TCP traffic for 60 seconds for each tested setting respectively; you can find the results inside the following plot:

The settings/parts are the following:

  • off: OpenWrt’s Firewall stopped (/etc/init.d/firewall stop)
  • on: OpenWrt’s Firewall started but without any offloading enabled
  • sw_flow: Netfilter’s software offloading enabled (flow_offloading)
  • hw_flow: Netfilter’s hardware offloading enabled (flow_offloading_hw)
  • xdp256: The eBPF IPv4 forwarding program attached to the XDP generic hook with the default package headroom of 256 Bytes
  • xdp32: The eBPF IPv4 forwarding program attached to the XDP generic hook with a custom package headroom set to 32 Bytes allowed by my patch
  • tc: The eBPF IPv4 forwarding program attached to the TC hook

Unfortunately, I couldn’t test XDP native yet because I don’t have any hardware around whose driver supports XDP.

As you can see and as I already mentioned, there is no performance gain from the XDP generic mode with the default 256 Bytes packet headroom due to the SKB re-allocation. Contrary to the patched XDP generic and TC, the network throughput about doubled compared to OpenWrt’s Firewall without any offloading.

Compared to Netfilter’s offloading implementations, there is also a performance gain, but admittedly only a small one. When we look at the Linux kernel source code here, this becomes plausible because the TC hook is located right before the Netfilter ingress hook. The XDP generic hook comes earlier than those two, even before taps (e.g., where tcpdump could listen).

So what’s next?

These are the upcoming milestones for the project:

  • Creation of a user-space program for loading and communicating with the eBPF program
  • Extending the user-space program with a firewall NAT/rule parser
  • Extending the eBPF program to apply the parsed firewall configuration on incoming packages
  • Evaluating the forwarding and dropping performance of the implementation

You can find the current eBPF IPv4 package forwarder, the XDP generic headroom patch, and the measurement and plotting script in my GitHub repository here: https://github.com/tk154/GSoC2024_eBPF-Firewall.

I will also upload the source code of the firewall there, which I am excited to implement in the upcoming weeks. I think the first small forwarding performance test already shows the potential of eBPF as a new offloading variant, and I haven’t even tested XDP native yet.

If you have any questions, don’t hesitate to ask them, and thank you for reading my first post.