GSoC 2017 – Final Milestone

tl;dr:
If you are looking for the work I have done for GSoC 2017, here are the principal repositories containing the source code and documentation:
– [1] ONOS
– [2] SDWN controller
– [3] SDWN agent

Also, check out the website that Johannes and I created to document how our two GSoC projects can be combined.

August Progress

In my last blog post I wrote that during the final coding phase I wanted to focus on applications for my controller platform – mainly an app that integrates my controller with Johannes’ OpenWifi server. While I was programming it, I noticed that I was getting tangled in unstructured dependencies between the different parts of my code. I realized that the controller needed a refactoring to better define its main application-facing interfaces. So I decided to modularize it into 4 separate pieces:

    the SDWN core API,
    its core implementation,
    a command-line interface,
    and a REST API.

With the refactoring done, I built two applications: the aforementioned OpenWifi integration and a simple client hearing map. Unfortunately I ran out of time just when adding features was fun again. The basics are all in place and working but I did not finish the more advanced applications such as the client load balancer or client authenticator that I mentioned in my last blog post.

On the more positive side, I really like how the newly structured controller behaves when adding features as well as how the OpenWifi integration turned out. A combined SDWN/OpenWifi setup is shaping up to become a neat management tool to operate a large deployment of LEDE nodes in which most of the initial configuration is automated. Nodes discover the OpenWifi server, download a configuration which makes them initiate a connection to the SDWN controller which gathers information about the nodes’ wireless capabilities and running access points. Throw in the hearing map and the nodes start reporting clients in their vicinity to the controller which makes that information available via its various APIs. Seeing it in action felt rewarding and dampened my initial disappointment of not getting everything done.
Johannes and I have put together a small website using GitHub pages which explains how to set up and use a combined SDWN/OpenWifi system.

Also during the past month, I have reached out to the ONOS developers about my work on the compatibility of ONOS’ fork of Loxigen and its upstream version. ONOS recently moved to a much more recent version of the loxigen-generated Java library for its OpenFlow subsystem which should make it easier for me to merge with it my modified ONOS. I want to explore if I can completely separate my code from the controller and have it provide the same functionality as external modules. This would of course greatly simplify future maintenance of the work I did.

The SDWN System

The following sections document the structure of the system that I have built and list possible applications.

The Controller

The SDWN controller that I have written comes as an OSGi bundle that gets deployed as an ONOS application. It relies on ONOS’ OpenFlow subsystem which manages the connection to the wireless switches in the network. Since I am using a custom OpenFlow protocol extension, I have added a corresponding protocol driver into ONOS’ south-bound interface which is responsible for the handshake with the SDWN agent. The SDWN controller’s core interacts with that driver and ONOS’ OpenFlow controller to create its abstraction of the network elements. It maintains so-called SDWN entities to represent the relevant wireless network resources and their relationships. For example, an access point is running on a network interface card which supports a certain set of transmission frequencies and rates. The controller would represent this state in the form of Java objects for the network interface card, its capabilities as well as the access points and set the references between them appropriately. This information is stored and made accessible through different APIs. If clients associate with the access point, the agent on the node notifies the controller which learns the client’s properties and stores the relationship with the AP. SDWN applications need not communicate with the wireless hardware directly but only work with the abstractions provided by the controller. There are also means for applications to subscribe to certain events such as the association of a new client or the reception of a probe request frame by an access point.

SDWN Applications

Applications can provide their services without having to interact directly with the network, they can leave communication details to the controller. For instance, the simple hearing map that I wrote subscribes to 802.11 management frame events. Every time the controller gets notified about such a frame by one of its APs, it informs the hearing map service. The service in turn stores the information about which AP on which switch received the frame on which frequency at what time and with how strong a signal.

Although I did not get to implement it, all the interfaces necessary to implement a blacklist of banned clients are in place. Simply register with the SDWN controller, hook into the stream of authentication and association request events, and deny unwanted clients based on their MAC address.

Or you could automatically push clients towards certain frequency bands: Query the hearing map for clients in the vicinity of an AP broadcasting at the desired frequency and check if they are currently associated with an access point on an unfavored channel. If yes, instruct that AP to disassociate and ban the clients for some time and grant their association request at the chosen target AP.

The Agent

To manage the network elements from the central controller, each of them needs to run an agent that maintains the connection, responds to queries, and executes commands. The SDWN agent is called wlanflow and it is built with the indigo OpenFow agent framework by the Floodlight project. It is available as a feed to integrate with the LEDE build system and uses UCI for configuration. Please refer to the instructions in the repository at GitHub (REPO LINK) about installation and configuration.
Wlanflow interacts with different other programs and services on the same machine. For example, it learns about most wireless capabilities through Linux’ netlink interface and subscribes to the standard Linux wifi soft-mac daemon hostapd via LEDE’s ubus IPC bus to receive notifications about incoming wifi management frames.

The Protocol

The SDWN controller and agent talk using an extended version of OpenFlow 1.3. The libraries for both the Java controller and the C agent are generated using a modified version of Loxigen.

Deploying the SDWN System

Like I said in the beginning of this blog post, I did not manage to realize all the ideas I had for this system. For this reason, the final product is a bit bare and lacks finish. Nonetheless, I encourage you to build a small installation and try out its features if you have spare wireless LEDE nodes lying around. I would appreciate your feedback and suggestions for improvements or new features.

You can find instructions on how to build and deploy the components of the SDWN system in their respective repositories which are listed at the top of this page.

Acknowledgments

Finally, I would like to thank Freifunk for letting me participate in GSoC again. Thanks to Andreas for organizing everything on Freifunk’s side and to my mentor, Julius.

GSoC 2017 – Milestone 2

Following the rather stark change of direction after the last milestone (see my last post), I have worked on the integration of my project with Johannes Wegener’s: OpenWifi.

July Progress

For my software-defined networking (SDN) agent, I have added support for configuration through a UCI config file as well as process management through procd. This ties the daemon in neatly with the LEDE/OpenWRT system. Now, parameters such as the SDN controller’s address are read from this file and the configuration can be reloaded at runtime without stopping the agent.
Using the UCI system also exposes the configuration parameters to Johannes’ OpenWifi system. He and I discussed the bootstrapping process with our mentor and we have come up with the following idea: When a newly installed LEDE/OpenWRT access point first boots, it discovers the OpenWifi server via mDNS and fetches its configuration from it. With the address contained in the configuration, my SDN agent on the access point is able to connect to the SDN controller and thus integrate automatically with an existing centrally managed deployment. In the event of a configuration parameter change (e.g. a switch to a different SDN controller), OpenWifi can trigger a configuration reload to quickly update all access points in the network.

On the controller side, I have implemented a REST client to interface with OpenWifi. Through it, the controller can register with the OpenWifi server. During the registration, it installs its address and OpenFlow listening port in the UCI configuration which later gets sent to access points.
I have also begun writing a REST interface for my controller to offer more comfortable management of SDN applications and the network state. Right now, I can query the controller about its resources: access points, switches and clients. With the basics in place, expanding the interface to expose more SDN functionality should be pretty straightforward.

Next Steps

During the final part of this year’s GSoC, I want to focus on adding functionality, testing and documentation. I will spend the remaining weeks of the project like this:
1) write an SDN application
2) expose the app’s functionality via the controller’s command-line and REST interfaces
3) test it on the university department’s testbed
4) document its usage
5) goto 1)

Since the foundation for the SDN applications is in place and running, I am optimistic about getting a lot done during August. I will start with a client hearing map that keeps track of associated and unassociated clients in the vicinity of the deployment’s access points. Leveraging the hearing map, I want to implement a client load balancer that distributes associated clients evenly across available access points. I will also look into automated channel selection to avoid interference between neighbouring access points.
Finally, I would like to wrap up the controller in a docker image for easy deployment.

GSoC 2017 – Milestone 1

June Progress

During the past weeks, I have mainly worked on LoxiGen. LoxiGen is a compiler which generates OpenFlow serialization and de-serialization libraries for C and Java. I have used the tool before and was able to build on my own work introducing the necessary message types for my GSoC project. Since I have chosen ONOS as my Software-Defined Networking (SDN) controller, I used ONOS’ fork of LoxiGen as a starting point. This required hard-coding some message types to make ONOS’ fork produce valid C libraries. I am planning to get in touch with LoxiGen’s maintainers soon to try and figure out if some of my work can be used towards a merge of the two diverted code bases.

[Edit: Major change of plan]

In an older version of this blog post, I wrote that I was going to implement a kernel module to enable the de-coupling of hostapd and the physical access point. Yesterday, I had a long discussion with my mentor and Johannes, another GSoC participant for Freifunk (read about his project here). We decided to drastically change the direction of my project. Instead of aiming for the (undoubtedly) cool and advanced feature of running hostapd as a Virtual Network Function, I am going to focus my efforts on a simpler use-case. The reasoning is to have a more stable and ready-to-use toolset for the management of larger OpenWRT/LEDE deployments in the end. In other words: Do less but do it well.

To this end, Johannes and I are going to work on a set of interfaces to make our projects compatible. The vision is as follows: I am going to write an SDN application that registers the ONOS controller with Johannes’ OpenWifi server. Whenever a new access point joins the network, it discovers the OpenWifi server and fetches its configuration from it. Included in this configuration are the address and port of the ONOS controller. Thus, the new network node is able to connect to the SDN controller without the need for manual configuration by the network operator.

Next Steps

As mentioned above, Johannes and I will have to establish interfaces for our projects to interact. We also need to set up a combined testbed to test our implementations. On my end, I will start by adding the possibility to configure the OpenWRT/LEDE agent that connects to the ONOS controller through UCI. That way, the agent’s configuration can be queried and altered through the OpenWifi REST API. This should be rather simple. Next, I will write a proper REST API for my controller as well as the application that communicates with the OpenWifi server. Then, I will add features for network management such as the ability to move clients to a specific access point or to ban them from connecting altogether. Lastly, I will write SDN applications for automatic network management, for example, a load balancer that distributes clients evenly across available access points that is powered by the data stored in a client hearing map.

Bringing a Little SDN to LEDE Access Points

Hi everyone!

My name is Arne Kappen and this is the beginning of my second participation in GSoC for Freifunk.

Last year, I implemented an extension for LEDE’s netifd which enabled network device handling logic to be outsourced to an external program and still integrate with netifd via ubus. My work included a proof-of-concept implementation of such an external device handler allowing the creation and configuration of OpenVSwitch OpenFlow switches from the central /etc/config/network file [1].

Sticking with Software-Defined Networking (SDN), this year I am going to provide the tools to build SDN applications which manage wireless access points via OpenFlow. The main component will be establishing the necessary message types for the control channel. I am going to extend LoxiGen to achieve this. In the end, there should be OpenFlow libraries for C and Java for the development of SDN applications and their agents running on LEDE.
I will also write one such agent and a control application for the ONOS platform to test my implementation.

My ideal outcome would be a REST interface putting as many of the APs configuration parameters under control of the SDN application as possible. Such a system could provide comfortable management of a larger deployment of LEDE access points and be a stepping stone for more complex use cases in the future.

I am looking forward to working with Freifunk again. Last year’s GSoC was a great experience during which I learned a lot.

[1] Last Year’s GSoC Project

Google Summer of Code 2016: External netifd Device Handlers – Final Milestone

TL;DR

FINISHING THE PROJECT

The past weeks have felt very satisfying in terms of coding. With the main structure in place, all that I had to do was add features, test, iron out the wrinkles and prepare my code for submission to the maintainer. Adding features was fun because it felt like taking big steps forward every day with immediate feedback.
There were a few stubborn bugs, though. Despite taking the better part of a week to find, they were — luckily — easy to fix. They usually required little more than changing the order in which code executed which meant swapping a few lines of code.
Rebasing the netifd source code on to the current version went very fast and resulted in three separate commits; two small ones to prepare the existing code base for my additions and one pretty big one adding my ~2000 line .c-file.

As this is the blog post wrapping up my Google Summer of Code, I am going to summarize the entire project. This probably means that I will repeat some of the points I have already explained in my previous posts.

GOALS MET

I set out to implement a way to open up OpenWRT/LEDE’s network interface daemon (netifd) for new device classes.
Until now, netifd was only able to handle device classes for which a handler was hard-coded into the daemon. I added a way to generate the necessary device handler stub from JSON descriptions and interface them over ubus with another process that handles all device-related actions such as creation and configuration. Netifd is more open to experimentation and does not require maintenance from someone introducing a new device class.
Configuration of these devices still happens in the familiar /etc/config/network file.

Along with the ubus interface in netifd, I wrote ovsd, an external device handler for Open vSwitch. Together with ovsd, netifd can create and configure Open vSwitch bridges without any Open vSwitch-specific code added to it. It simply parses the configuration in /etc/config/network, sees that there is an interface on a device with type ‘Open vSwitch’, uses this name to look up the corresponding device handler from a list and calls the ‘create’ function that is part of the device handler interface.
The Open vSwitch device handler stub then relays the command along with the configuration blob to ovsd via ubus.

Ovsd processes the command asynchronously and answers using the ubus subscription mechanism. Netifd can then bring up the device as usual and attach protocol handlers and interfaces to it.

My work on netifd is not likely to get included upstream before GSoC ends which is why I have created a patch with my changes and put it in a repository here. The repo includes the LEDE source code as a git submodule and is easy to build.
The ovsd source code is hosted at GitHub along with instructions on how to install it.

DETAILS OF THE SUBMITTED WORK

This example file demonstrates all the available configuration options for Open vSwitch devices in a possible scenario featuring an Open vSwitch bridge with interface eth0 and a fake bridge on top of it:

# /etc/config/network
config interface ‘lan’
    option ifname ‘eth0’
    option type ‘Open vSwitch’
    option proto ‘static’
    option ipaddr ‘1.2.3.4’
    option gateway ‘1.2.3.1’
    option netmask ‘255.255.255.0’
    option ip6assign ’60’

    option ofcontrollers ‘tcp:1.2.3.2:9999’
    option controller_fail_mode ‘standalone’
    option ssl_cert ‘/root/cert.pem’
    option ssl_private_key ‘/root/key.pem’
    option ssl_ca_cert ‘/root/cacert_bootstrap.pem’
    option ssl_bootstrap ‘true’

config interface ‘guest’
    option type ‘Open vSwitch’
    option proto ‘static’
    option ipaddr ‘1.2.3.5’
    option netmask ‘255.255.255.0’

    option parent ‘ovs-lan’
    option vlan ‘2’
    option empty ‘true’

The lines set apart are Open vSwitch-specific options. They configure OpenFlow settings, control channel encryption and the nature of the device itself, which can either be a ‘real’ or a ‘fake’ bridge on a parent bridge and VLAN tagging enabled.

This is the JSON description from which the device handler stub is generated:

# /lib/netifd/ubusdev-config/ovsd.json
{
    “name” : “Open vSwitch”,
    “ubus_name” : “ovs”,
    “bridge” : “1”,
    “br-prefix” : “ovs”,
    “config” : [
        [“name”, 3],
        [“ifname”, 1],
        [“empty”, 7],
        [“parent”, 3],
        [“vlan”, 5],
        [“ofcontrollers”, 1],
        [“controller_fail_mode”, 3],
        [“ssl_private_key”, 3],
        [“ssl_cert”, 3],
        [“ssl_ca_cert”, 3],
        [“ssl_bootstrap”, 7]
    ],
    “info” : [
        [“ofcontrollers”, 1],
        [“fail_mode”, 3],
        [“ports”, 1],
        [“parent”, 3],
        [“vlan”, 5],
        [“ssl”, 2]
    ]
}

The first four fields tell netifd the type of the devices and the name of the external handler to connect to via ubus. “bridge” and “br-prefix” signal the bridge capabilities of the devices and give a short prefix to prepend to devices of type Open vSwitch creating devices named “ovs-lan” and “ovs-guest” for the interfaces “lan” and “guest”, respectively.
The “config” and “info” field detail the configuration parameters and their data types for device creation and for responses to the ‘dump_info’ method of the external device handler (see my earlier blog post).
I have created a manual on how to write a JSON description of an external device handler that goes into greater detail. You can find it here.

POSSIBLE LIMITATIONS AND OPEN WORK

Because of the nature of the device handler I implemented, I could only test scenarios that arise from using Open vSwitch. These are bridge-like devices by design and not every device class someone might want to integrate with netifd will behave like them. I had to anticipate much of the behavior for non-bridge-like devices trying to make the ubus interface device class agnostic.

Also, while I tested ovsd with all the complex setups I could think of using fake bridges and wireless interfaces, there are probably edge cases where my implementation is insufficient. Ovsd may have to become stateful at some time.

At the moment, the JSON files from which the device handler stubs are created are a bit “human-unfriendly”. Parsing the JSON objects fails unless they are written on a single line with proper EOF termination. Allowing pretty-printed JSON would greatly increase readability. What’s more, the parameters’ data types are cryptic enumeration values from libubox. Another translation layer turning numbers into readable types like “string” would also help users read and write description files.

IMPROVEMENTS TO MAKE

In the future, I would like to add a way for external device handlers to send detailed feedback about requests they receive back to netifd within the context of the request. This way authors of external device handlers could provide device-specific information such as specific error messages when a command fails.
All the building blocks for such a mechanism are there:
  – ubus replies that are logically connected to an ongoing request and
  – the possibility to tell netifd what messages to expect via an entry in the JSON description file.

This way, messages and their formats could be defined by the authors of external device handlers on a per-device-class — and even a per-command — base. Netifd would then be able to handle these messages and write them to the logs along with information about the context of the ongoing transaction.

MY EXPERIENCE WITH GSOC

All in all, GSoC was a blast. Although challenging and frustrating at times, I am happy to have done it. This was the first time I had to read other people’s code to this extent and at this level of — for lack of a better word — sophistication. It took me the better part of a year to really get a grip on the code base when I was working with it as part of the student project at TU Berlin but once I had a feeling for its structure, playing around with the features I added was fun. It feels rewarding to have worked on and contributed to “real world” free software.
From the organizational, side I am very happy with both Freifunk’s and Google’s way of managing the process. I always knew what was expected of me and was provided the necessary information in advance.

ACKNOWLEDGEMENTS

Now that my first GSoC is over, some thanks are due. First and foremost, I would like to thank my mentor and advisor Julius Schulz-Zander for introducing me to GSoC and for his counsel throughout the summer. Thanks to Felix Fietkau, original author of netifd and its maintainer, of whom I’ve learned a lot both indirectly by working with his code and directly when receiving feedback on my work. Finally, I want to thank Freifunk for letting me do this project and — of course — Google for organizing GSoC.

Google Summer of Code 2016: External netifd Device Handlers – Milestone 1

OVERVIEW OF THE LAST WEEKS
During the last 5 to 6 weeks I have implemented the possibility to include wireless interfaces in Open vSwitch bridges, rewritten a lot of the code for creating bridges with external device handlers and brought my development environment up to speed. I am now working with an up-to-date copy of the LEDE repository.
I have also implemented the possibility for users of external device handlers to define what information and statistics of their devices look like and to query the external device handler for that data through netifd.

CHANGES TO THE DEVELOPMENT ENVIRONMENT
So far, I have been using quilt to create and manage patches for my alterations of the netifd code.
One day they were completely broken. I still do not know what and how it happened but it was not the first time and this time recovery would have been way too tedious.
This is why I switched to a git-only setup. I now have a clone of the netifd repo on my development machine that is symlinked into the LEDE source tree using the nice ‘enable package source tree override’ option in the main Makefile. I used the oppportunity to update both the LEDE source tree and the netifd repository to the most recent versions.
Before, I was working on an OpenWRT Chaos Calmer tree, because of a bug causing the Open vSwitch package to segfault with more recent kernels.
Now, everything is up-to-date: LEDE, netifd and Open vSwitch.

MY PROGRESS IN DETAIL

More Dynamic Device Creation
In actual coding news, I have refined the callback mechanism for creating bridges with external device handlers and the way they are created and brought up.
Previously, a bridge and its ports were created and activated immediately when /etc/config/network was parsed. Now, the ubus call is postponed until the first port on the bridge is brought up.
Because of the added asynchronicity, I had to add a ‘timeout and retry’-mechanism to keep track of the state of the structures in netifd and the external device handler.

A few questions have come up regarding the device handler interface. As I have explained in my first blog post, I am working on Open vSwitch integration into LEDE writing an external device handler called ovsd. Obviously, this is very useful for testing as well.
I have come across the issue of wanting to disable an bridge without deleting it. This means bringing down the bridge and removing the L2 devices from it. The device handler interface that I mirror for my ubus methods doesn’t really have a method for this. The closest thing is ‘hotplug remove’, which using feels a bit like a dirty hack to me.
I have reached out no netifd’s maintainer about this issue. For the meantime, I stick to (ab)using the hotplug mechanism.

On the ovsd side I have added a pretty central feature: OpenFlow controllers. Obviously, someone who uses Open vSwitch bridges is likely to want to use its SDN capabilities.
Controllers can be configured directly in /etc/config/network with the UCI option ‘ofcontrollers’:

config interface ‘lan’
        option ifname ‘eth0’
        option type ‘Open vSwitch’
        option proto ‘static’
        option ipaddr ‘1.2.3.4’
        option gateway ‘1.2.3.1’
        option netmask ‘255.255.255.0’
        option ofcontrollers ‘tcp:1.2.3.4:5678’
        option controller_fail_mode ‘standalone’

The format in which the controllers are defined is exactly the one the ovs-vsctl command line tool expects.
The other new UCI option below ofcontrollers configures the bridge’s behavior in case the configured controller is unreachable. It is a direct mapping to the ovs-vsctl command ‘set-fail-mode’. The default behavior in case of controller absence is called ‘standalone’ which makes the Open vSwitch behave like a learning switch. ‘secure’ disables the adding of flows if no controller is present.

Function Coverage: Information and Statistics
Netifd device handlers have functions to dump information and statistics about devices in JSON format: ‘dump_info’ and ‘dump_stats’. Usually, these just collect data from the structures in netifd and the kernel but with my external device handlers, it is not as simple. I have to relay the query to an external device handler program and parse the response. Since the interface is generic, I cannot hard-code the fields and types in the response. This is why I relied once more on the JSON data type description mechanism that I have already used for dynamic creation of device configuration descriptions.
In addition to the mandatory ‘config’ description, users can now optionally provide ‘info’ and/or ‘stats’ fields. Just like the configuration descriptions they are stored in the stub device handler structs within netifd where they are available to serve as blueprints for how information and statistics coming from external device handlers have to be parsed.

For my Open vSwitch setup, it currently looks like this in /lib/netifd/ubusdev-config/ovsd.json:
{
    “name” : “Open vSwitch”,
    “ubus_name” : “ovs”,
    “bridge” : “1”,
    “br-prefix” : “ovs”, 
    “config” : [
        [“name”, 3],
        [“ifname”, 1],
        [“empty”, 7],
        [“parent”, 3],
        [“ofcontrollers”, 1],
        [“controller_fail_mode”, 3],
        [“vlan”, 6]
    ],
    “info” : [
        [“ofcontrollers”, 1],
        [“fail_mode”, 3],
        [“ports”, 1]
    ]
}

This is how it looks when I query the Open vSwitch bridge ‘ovs-lan’:

THE NEXT STEPS

During the weeks to come I want to look into some issues which occurred sometimes when I disabled and re-enabled a bridge: Some protocol-realated configuration went missing. This could mean that sometimes the configured IP address was gone. Something which could help me overcome the problem is also in need of some work: reloading/reconfiguring devices.
Along with this, I want to get started with the documentation to prepare for the publication of the source code.

GSoC 2016 Introduction: external device handlers for netifd

HELLO WORLD

It’s time I started blogging about my Google Summer of Code project with Freifunk.

To begin, let me introduce myself. I am Arne, computer science student at TU Berlin and pursuing my Bachelor’s degree. This is my first GSoC — and the first time I contribute to an Open Source software project, so, naturally, I’m pretty excited to get to know the process.

My project aims at extending OpenWRT/LEDE’s network interface daemon (netifd).

I’ve familiarize myself with the inner workings of netifd while I was working on a student project last semester. The result of that student project will assist me in realizing the GSoC project. Moreover, the existing source code will partially build the foundation of the new device handler which will be realized in this project.

 

THE PROJECT

Here’s the general idea: Netifd allows the user — as the name suggests — to create and configure network devices and interfaces. Per device class, there is a hard-coded structure called a ‘device handler’. Each device handler exposes an interface for operations such as creation or re-configuration of device instances of its class.

The point I’m tackling is the structures hard-codedness. Today, whenever someone wants to introduce a new device class, is necessary to alter the netifd code base and maintain these changes. The proposed mechanism allows to realize external device handlers as separate programs communicating via the bus system ubus. Accordingly, to introduce a new device class into netifd, one just needs to implement device handling logic and link it to netifd. Thus, no maintenance — or knowledge of the innermost workings of netifd — is necessary.

Building on my work from the aforementioned class I’ll write a device handler to integrate Open vSwitch support into OpenWRT/LEDE using netifd. The ‘ovsd’ as it is called will relay calls to the device handler interface via the ‘ovs-vsctl’ command line utility to set up Open vSwitch bridges and ports.

 

MY DEVELOPMENT ENVIRONMENT

I am hosting my code in a git repository that’s included in the GitLab of the INET department which is employing me at TU Berlin. Once the code becomes usable, it will appear on GitHub here.

We also have a repository providing an OpenWRT/LEDE feed that bundles the Open vSwitch software with ovsd: (link will follow)

 

Testing is done on a PC Engines Alix 2 board which is part of our testbed:

 

WHERE I AM AT

As of today I have realized a mechanism to generate device handler stubs within netifd when the daemon is first started and before it parses /etc/config/network. The device class’ parameters, such as its name in the ubus system and most importantly the format of its configuration, are stored in JSON files in /lib/netifd/ubusdev-config/. The logic to parse a configuration format from JSON files existed already within netifd but was only used for protocol handlers before. I adapted it to generate device handlers dynamically.

When such a device handler is generated, it subscribes to its corresponding external device handler using ubus. This way, the latter can generate events asynchronously for the former to react to.

In order for this to work, the external device handler must be up and running before netifd attempts the subscription.

I also realized a simple proof-of-concept implementation that works in one simple case: create an ovs-bridge with one or more interfaces like this example /etc/config/network file demonstrates:

 

config interface ‘lan’

    option ifname ‘eth0’

    option type ‘ovs’

    option proto ‘static’

    option ipaddr ‘172.17.1.123’

    option gateway ‘172.17.1.1’

    option netmask ‘255.255.255.0’

This will create an Open vSwitch bridge called ‘ovs-lan’ with the port ‘eth0’ — and that’s about all it does right now. Error handling is missing and more complex options like setting OpenFlow controllers or adding wireless interfaces don’t work yet.

 

THE ROAD AHEAD

Among the first things I’ll tackle when GSoC’s coding phase begins are adding the possibilities to incorporate WiFi-interfaces to the bridges created with external device handlers and introducing the missing parts of the device handler interface. Since I’m dealing with netifd and the external device handler which is an independent process running asynchronously, getting their state to stay in sync will take some work. I need to think about the way the callback system that comes with ubus’ pubsub-mechanism will function. In the end, it is supposed to be abstract enough to work not only for my Open vSwitch use case but for any external device handler.

Then, further into the coding phase, I want to increase feature coverage of the Open vSwitch options, so that users can assign OpenFlow controllers for their bridges like so:

 

config interface ‘lan’

    option ifname ‘eth0’

    option type ‘ovs’

    option proto ‘static’

    option ipaddr ‘172.17.1.123’

    option gateway ‘172.17.1.1’

    option netmask ‘255.255.255.0’

    option of-controller ‘1.2.3.4:5678’

In the end I would like to have the mechanism implemented and documented so that others can build on it. Documenting my work is especially important to me, because I found myself frustrated with the scarcity of the netifd documentation more than once before. I wish for my code to become a part of OpenWRT/LEDE and be extended and improved in the future and I would like to make it easy for anyone insterested to doing that with a helpful manual and commented code.

I’m excited to get started and hope to find the time to blog about my progress here, regularly.