POX: a Python platform for writing OpenFlow software, now on a named release line
The POX network software platform
At a glance
- What is it?
- POX began as an OpenFlow controller and can also act as an OpenFlow switch, and its architecture is a component system where every module exposes a launch() function, which makes it a platform for experimenting with networking software rather than a finished controller.
- Who is it for?
- Adopt POX if you are teaching or experimenting with OpenFlow and want to write controller behaviour in Python in a single file, and if OpenFlow 1.0 with the Open vSwitch extensions is the target you need. Do not adopt it for a production network, because the project supports only OpenFlow 1.0, is a research platform with no release history on GitHub, and its default branch is an experimental one.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 31 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
From a controller to a platform for network software
POX is described as a networking software platform written in Python. The README explains the history in one line: POX started life as an OpenFlow controller, but can now also function as an OpenFlow switch, and can be useful for writing networking software in general. That is the whole pitch. The audience is people who want to experiment with network behaviour in a language they already know, mostly students, researchers and engineers prototyping forwarding rules. The protocol position matters for any evaluation: POX currently supports OpenFlow 1.0 and includes special support for the Open vSwitch and Nicira extensions. There is no mention of OpenFlow 1.3 or of the newer versions of the protocol, so a project that needs modern OpenFlow semantics or the OpenFlow 2.x and beyond protocol family is looking at the wrong tool. The project has a homepage hosting the full documentation and a default branch named gar-experimental.
Everything is a component with a launch() function
The boot mechanism is unusually simple to explain, which is the main pedagogical value of the platform. The script pox.py takes a list of component names on the command line, locates the components, calls their launch() function if it exists, and then transitions to the up state. Components are essentially Python modules with a few POX specific conventions, and they are looked for everywhere Python normally looks, plus the pox and ext directories in the repository. That last detail is what makes the platform extensible: dropping a module into ext/ is enough to have it found and launched, with no registration step, no plugin manifest, and no packaging ceremony. The name of a component on the command line is a dotted path such as forwarding.l2_learning, and options for a component are passed after the component name, which are then handed to that module's launch() function. The result is that the smallest interesting POX program is one module with one function.
Running it: the command line and its own options
The launcher is invoked with a sequence of components and their options.
./pox.py [pox-options...] [component] [component-options...] ...The script tries to find a Python 3 interpreter on its own, looking for a copy of PyPy in the main POX directory and using it if present, which the README notes can be a potentially large performance boost, and otherwise looking for python3 and falling back to python. You can of course invoke the interpreter yourself, for example by running python3 pox.py. POX has a small number of options of its own, of which two are listed: --verbose prints stack traces for initialisation exceptions, and --no-openflow stops the openflow module from starting automatically, which is the option to reach for when you are running POX purely as a platform and do not want the OpenFlow service binding a port. Component options are, by contrast, entirely the component's own business, and the README points you to each component's documentation for those.
Running as a controller, and switching on the learning switch
Two examples in the README show the shape of real invocations. The first starts a single component, the layer two learning switch, with no arguments at all, which is enough to run POX as a learning switch that learns MAC addresses and installs flow rules. The second runs POX as an OpenFlow controller and configures the address and port it listens on, by passing those options to the openflow._01 component.
./pox.py forwarding.l2_learning ./pox.py openflow.of_01 --address=10.1.1.1 --port=6634The port 6634 is the classic OpenFlow controller port, and the component naming with the numeric prefix inside the module name indicates an ordering convention inside the openflow package, which matters when several components in that package are launched together and their order has to be deterministic. Because options are positional after the component name, a command line reads as a sequence of separate programs rather than one global configuration, and that is the model to internalise if you write your own components.
Version names, Python 3, and the branch layout
POX versions are named rather than numbered, which is worth understanding because the names carry the platform story. Starting with POX gar, the project officially requires Python 3, and the last version with support for Python 2 was POX fangtooth. So a fork of POX that predates the Python 3 migration is on fangtooth, and everything from gar onward is Python 3 only. The repository layout adds detail: the root holds pox.py as the entry point, the pox/ package for the core modules, ext/ for external components, tools/ for helpers, tests/ for the test suite, plus setup.cfg, a .pylint configuration, a NOTICE file and a LICENSE. The licence is Apache-2.0. The default branch is gar-experimental, which is the branch to think carefully about, because it means the version you get by default is not necessarily the stable line the documentation describes. There are no GitHub releases, so a named version is the unit of reference rather than a tag you can install from.
Where POX is the wrong choice
The limits are clear enough to state plainly. The protocol ceiling is OpenFlow 1.0, so any design that assumes flow table counters, group tables, or the richer matching semantics of later protocol versions will not work without changes. The platform is a research and teaching tool, and the README itself says it is purposely brief and points you to the full documentation, which signals a project where you are expected to read source. The performance ceiling is Python: the PyPy note is presented as a potential boost rather than a tuned product, and any deployment where throughput matters is a deployment where you would be writing the controller in something else. The alternative worth naming is writing directly against a switch SDK such as the OpenFlow Python or Ryu bindings, which gives you the same language without a component framework, at the cost of losing the bundled components, the ext/ drop-in model, and the ready made layer two learning switch that makes a first experiment a single command. POX earns its place in teaching and prototyping, and those are exactly the jobs it was built for.
Editorial conclusion
Adopt POX if you are teaching or experimenting with OpenFlow and want to write controller behaviour in Python in a single file, and if OpenFlow 1.0 with the Open vSwitch extensions is the target you need. Do not adopt it for a production network, because the project supports only OpenFlow 1.0, is a research platform with no release history on GitHub, and its default branch is an experimental one. Verify first which branch you actually want, since the default is gar-experimental while the documented stable line is gar.
Frequently asked questions
How do I start POX as an OpenFlow controller on a specific port?
Pass the options after the openflow.of_01 component name, for example ./pox.py openflow.of_01 --address=10.1.1.1 --port=6634. The README notes that options given after a component name are passed to that module's launch() function.
What OpenFlow version does POX support?
The README states that POX currently supports OpenFlow 1.0 and includes special support for the Open vSwitch and Nicira extensions. POX can act as an OpenFlow controller or as an OpenFlow switch.
Which Python versions does POX run on?
POX versions are named. Starting with the gar version POX officially requires Python 3, and the last version supporting Python 2 was fangtooth. The launcher looks for a PyPy copy in the POX directory, then for python3, and falls back to python.
How do I add my own component to POX?
Components are Python modules with a few POX specific conventions, and they are looked for everywhere Python normally looks plus the pox and ext directories. Dropping a module into ext/ makes it discoverable, and giving it a launch() function lets it start from the command line.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/noxrepo-pox)Was this useful?