Composing SDN Policies (text)
  
  
  
    
      
      by
      Sasha Shkrebets
      
         —
    
  
  
  
  
  
    
      last modified
    
    Mar 20, 2023 08:06 AM
  
  
  
  
  
  
                   We are continuing our module on programming SDNs, and
we are now starting a lesson on composing SDN control.
This lesson will have two parts.
The first part of the lesson will
talk about the concepts of composing SDN control. 
                
            
            
        
                             
                             Welcome back. 
We are continuing our module on programming SDNs, and 
we are now starting a lesson on composing SDN control. 
This lesson will have two parts. 
The first part of the lesson will 
talk about the concepts of composing SDN control. 
The second part of the lesson will dive into a programing language 
called Pyretic which allows a programmer to compose SDN control. 
Networks perform many tasks. 
And if we think about how we might write an application that 
sits on top of an SDM controller that performs the wide variety of 
network tasks that an operator might want to perform, we might first 
consider writing a single monolithic application 
that performs all of those functions together. 
For example, the application might monitor or 
count the traffic volumes for particular traffic flows. 
It might route the traffic to different locations. 
It might apply firewalling policies. 
And it might also try to load balance the traffic across different servers. 
Now, the problem with a single monolithic application like this is 
it becomes very hard to program, test, debug, reuse, and port. 
Imagine, for example, that we wanted to test a 
certain component or reuse a particular component from this application. 
Well, suddenly we have a very big control program that is relatively unmanageable. 
A solution to this problem is to modularize the control so that 
the programmer writes separate modules, each 
of which performs a distinct operation. 
So, the operator might write a module that performs monitoring that is separate 
from the module that performs routing, firewalling, and so forth. 
This is much easier to program, test, and debug. 
And it's also easier for a programmer to 
reuse or port different components of this control application. 
However, getting the modules to play nice with one another is complicated. 
The controller has to perform some amount of arbitration among these 
modules because they're not just tenants that reside on the same control platform. 
In a multitenant environment, each module would control a 
different portion of the traffic guaranteeing that they wouldn't interfere. 
So, it would be relatively easy to partition the rule 
space, link bandwidth, and various network events across these different modules. 
However, in a control program, such as the one that 
we are talking about, different modules affect the same traffic. 
For example, the same traffic that's being monitored is 
also subjected to the routing, firewalling, and load balancing policies. 
So, each of these modules partially specifies how to handle traffic. 
And yet, these modules need to be combined, somehow, into a 
single complete control application that correctly 
implements the network operator's intended policy. 
The approach to this problem is to apply what is called composition. 
There are two types of composition operators. 
One is parallel composition where the 
control module performs multiple operations simultaneously. 
For example, the operator might want the control program 
to perform counting and forwarding on the same traffic stream. 
The second type of composition is called sequential composition. 
In this case, we perform one operation and then the next. 
For example, the network operator might want to first apply firewalling rules 
to the set of traffic before sending in the traffic through a learning switch. 
Let's now look at some example applications 
that use both parallel composition and sequential composition. 
Let's first have a look at parallel composition. 
Suppose that we would like to write a control 
program that both monitors traffic arriving on a particular source 
IP address and routes the traffic to different output 
ports depending on the value of the destination IP address. 
Now, in this case, we want both of these operations to happen at the same time. 
So, we apply parallel composition which produces a set of rules that 
effectively allows both of these operations to occur simultaneously. 
Note that, with this paradigm, we do not have 
to worry about which OpenFlow rules to install first. 
The controller platform automatically takes care of that for us. 
Let's now take a look at 
an example application that requires sequential composition. 
Suppose that we would like to implement a server load balancer whereby the 
load balancer spreads client traffic across multiple server replicas. 
There may be a public IP address for the service, for 
example, in this case 1.2.3.4, to which clients send their traffic. 
That load balancer then splits the traffic based on the client's source IP address 
and then rewrites the destination server IP address based on the client's IP. 
After rewriting the server's IP address, the load 
balancer then routes the traffic to the appropriate replica. 
This application requires what is known as sequential composition. 
First, we need to perform the load balancing 
operations of matching on a particular source IP address 
and, subsequently, rewriting the destination IP address accordingly, and 
then forwarding the traffic to the appropriate output port. 
As before, the controller composes these rules into a single 
set of rules that can be installed in the switches. 
Traffic can also be divided over modules. 
We can use certain predicates to specify which traffic traverses which 
modules based on both the input port and other fields in the packet header. 
For example, we can use a predicate to specify that if the destination port is 
not port 80, then we would like to perform monitoring and routing in parallel. 
But if the destination port is port 80, 
we'd like to perform load balancing followed by routing. 
Note that each module only partially specifies what should 
happen to traffic, leaving some flexibility to other modules. 
This avoids tying a particular module to a specific 
setting, thus making the modules more self-contained and portable. 
For example, when we applied load 
balancing followed by routing, the load balancer 
did not need to know how routing was being performed in that network. 
Therefore, if we wanted to use the load 
balancer in a different network, it would be relatively 
easy to reuse that component, even in a network 
where routing was performed in a completely different way. 
Another important feature of policy composition is that each 
module should have an abstract view of the topology. 
This abstract topology can implicitly encode constraints. 
For example, if the policy is intended 
to prevent two hosts from communicating with one 
another, we simply ensure that the logical 
typology has no path between those two hosts. 
The logical typology looks just like a normal network. 
But it prevents each module from overstepping or performing actions 
on parts of the network over which it has no purview. 
In other words, the logical typology hides irrelevant details from the modules. 
So, for example, the load balancer would not see such details 
as the internal topology, or any routing changes, or any routing changes. 
In summary, SDN control programs perform many tasks on the same traffic. 
The requirements for composing SDN control are 
compositional operators that specify how to compose 
policies and a logical switch abstraction that 
hides irrelevant details from each of these modules. 
In the next part of the lesson, we will look 
at a language called Pyretic that is built on POX. 
Pyretic implements both compositional operators 
and a logical switch abstraction. 
