OpenVSwitch programming (I)
For those not familiar with OpenVSwitch, its is a system that implements all the functionalities of a switch in software (or with some hardware support). It consists on a kernel module that performs the switching based on installed rules, user space daemons that are responsible for higher level logic and some command line tools for controlling all these elements. This is a diagram of the main elements (obtained from here):

OpenVSwitch (OVS) is focused on exposing an OpenFlow interface, but other managements APIs could be implemented on top of the existing system. However, OpenVSwitch and OpenFlow are becoming steadily the main standards in the SDN market, so I don't know if there are plans for implementing alternative APIs. And most of the things you can do with OVS could also be done with standard Linux commands, but OVS provides a common, simple interface for programming the switch while being integrated at the core of the networking system in the kernel.

With OpenVSwitch we create a virtual switch (a datapath in OVS terminology) where we install rules that, for packets that match a rule (flow matches), some actions are performed. For example we could install a rule like "packets with TCP port destination 80 are forwarded to port 5 in the datapath. There are two different ways we can install these rules and program the datapath:
Reactively
It is the typical OpenFlow programming model: you install rules in the OVS datapath and, for packets that do not match any of those rules, packets will go up (the upcall) to a controller. Then some software that implements the high level logic will determine what to do with that packet: it will inspect the packet, generate a new rule, insert the rule in OVS and execute the packet again.
This is a good programming model but has some problems:
- There can be important differences in throughput depending on how we communicate with OVS. As packets must go up to the controller in user space (the upcall), the number of steps (and copies) in that travel will affect negatively to the number of new connections we can process. More on this later on a following post.
- You must realize that this will happen for any new packet, and new packets can come very fast, in some cases faster than you insert new rules. Fast OpenFlow clients with remote access to OpenFlow hardware switches can usually insert about 250-500 new rules per second. They are not too many, specially if we are being port scanned and all those packets generate upcalls...
- You must implement some kind of accountancy system that delays new packets inspection/processing when they are similar to packets currently being inspected/processed. If you add some level of parallelism here (ie, with a pool of reader of new packets), this accountancy system can get a bit complicated...
Proactively
In this model, you must generate a rule in advance for any possible packet the network could see. This is a good solution for simple, static topologies (ie, a switch-like scenario where “any packet from container X with destination Y goes to container Y and any packet from container Y with destination X goes to container X”). However, this programming model is only possible with OVS 2.x as it implements “wildcard matches” (or “megaflows”): wildcards in the flow matches that allow matches for things like “any IP”, “any TCP port”, etc. If this feature is not available, the OVS controller would have to set a rule for each possible combination of IPs, ports, etc...
So this model is definitely the best model in performance terms. You can set wildcard matches for all possible flows and no packets will ever go to user space (and if this happens, you have a bug in your logic), or you can also deliberately leave some flows out of the wildcard matches so your controller will receive them. For example ARP requests that can be answered by the controller, initial/final TCP packets matched by having SYN or FYN flags (so we can keep track of new/finished connections), packets that are tunneled by the controller with some encapsulation protocol not supported at datapath ports, etc)