HowTo/WriteOFv3Rspecs

Writing Openflow version 3 rspecs

This page describes how to write  GENI compliant Openflow rspecs (OF v3 rspecs). These new rspecs are supported by FOAM, the new Openflow AM. This page also provides instructions and how to convert Expedient rspecs to the new form of rspecs. For a detailed explanation of the tags and attributes look at this specification page.

If you want to check the validity of the format of an rspec, check  here.

Openflow Slivers

In an Openflow Aggregate, an experimenter can control how the packets are forwarded within the network, using a custom controller running in an external compute resource. In the general case an Openflow Aggregate consists of Openflow-enabled devices(e.g. switches) which forward packets based on instructions received by the controllers.

The traffic of an Openflow network can be sliced, using matching rules on the traversing packets. A set of rules that describes part of the passing traffic is called a flowspace. A flowspace can be defined based on the datapath ids (aka dpids) and ports that the packets are going through, and/or based on their headers. Datapath is a virtual network device that is controlled using the Openflow protocol and can forward packets. So for example a switch running an Openflow compatible firmware might be a datapath.

More details about how Openflow works and about which fields of the packet headers can be used in flowspaces can be found in the  Openflow Spec 1.0.0 and in the  Openflow website.

For example a sliver on an Openflow network might request for :

"All packets coming in port 5 on datapath 15, and have a source IP address in subnet 10.10.10.0/24."

Writing OpenFlowv3 request rspecs

The best way to understand and write OF v3 rspecs is by looking at example rspecs. Keep in mind that the rspec is merely a structured representation of flowspaces that describe the traffic that an experiment wants to control.

This  example rspec, is a complete example. In this wiki page you can also find other simpler examples.

In essence your rspec should:

  1. Start with the <rspec> and the <openflow:sliver> tags :
    <?xml version="1.1" encoding="UTF-8"?>
    <rspec  xmlns="http://www.geni.net/resources/rspec/3"
            xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:openflow="http://www.geni.net/resources/rspec/ext/openflow/3"
            xs:schemaLocation="http://www.geni.net/resources/rspec/3
                  http://www.geni.net/resources/rspec/3/request.xsd
                  http://www.geni.net/resources/rspec/ext/openflow/3
                  http://www.geni.net/resources/rspec/ext/openflow/3/of-resv.xsd"
        type="request">
        
        <openflow:sliver email="user@geni.net" description="My GENI experiment" ref="http://www.geni.net">
    
            <!-- rest of rspec -->
    
        </openflow:sliver>
    </rspec>
    
  1. Specify where your controller is running. E.g.:
     #!xml
    <openflow:controller url="tcp:example.geni.net:9933" type="primary" />
    
  1. Organize the datapaths that are relevant to this sliver within groups. The best way to construct the <openflow:datapath> elements is by copying them from the advertisement rspecs. E.g if this Download is the advertisement rspec, and you want :
  • ports 7 and 20 of datapath with dpid 06:a4:00:12:e2:b8:a5:d0
  • ports 50 and 71 of datapath with dpid 06:af:00:24:a8:c4:b9:00

Then you can construct a group that looks like :

 #!xml
 <openflow:group name="mygrp">
   <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+datapath:06:a4:00:12:e2:b8:a5:d0" 
                      component_manager_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+authority+am" 
                      dpid="06:a4:00:12:e2:b8:a5:d0">
     <openflow:port name="GBE0/7" num="7"/>
     <openflow:port name="GBE0/20" num="20"/>
   </openflow:datapath>


   <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+datapath:06:af:00:24:a8:c4:b9:00" 
                      component_manager_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+authority+am"
                      dpid="06:af:00:24:a8:c4:b9:00">
     <openflow:port name="26" num="50"/>
     <openflow:port name="47" num="71"/>
   </openflow:datapath>

 </openflow:group>
  1. Specify your flowspace. E.g. if you want for the above group to get all traffic that is sourced or destined to the IP subnet 10.1.1.0/24 and uses tcp port 80, then you will need two <openflow:match> tags, one to match the packets that are sourced from that subnet and one to match the packets that are destined to that subnet. Keep in mind that your flowspace is the union of the traffic that is described by each. If you need to get a list of all possible filters and how the tags are named look here.
     <openflow:match>
       <openflow:use-group name="mygrp" />
       <openflow:packet>
         <openflow:dl_type value="0x800" />
         <openflow:nw_src value="10.1.1.0/24" />
         <openflow:nw_proto value="6, 17" />
         <openflow:tp_src value="80" />
       </openflow:packet>
     </openflow:match>
    
     <openflow:match>
       <openflow:use-group name="mygrp" />
       <openflow:packet>
         <openflow:dl_type value="0x800" />
         <openflow:nw_dst value="10.1.1.0/24" />
         <openflow:nw_proto value="6, 17" />
         <openflow:tp_dst value="80" />
       </openflow:packet>
     </openflow:match>
    

Notice that although we need to match on IP source/destination and on the transport protocol port, we also applied filters to ensure that the packet is an IP packet and that the IP protocol is TCP or UDP. Openflow can filter on any Layer 2, Layer 3 or Layer 4 header field but you would need to match the type on the lower level in order to filter at the higher one, e.g. in order to match on IP fields you need to first ensure that the packet is indeed an IP packet.

Done! The complete rspec looks like :

<?xml version="1.1" encoding="UTF-8"?>
<rspec  xmlns="http://www.geni.net/resources/rspec/3"
        xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:openflow="http://www.geni.net/resources/rspec/ext/openflow/3"
        xs:schemaLocation="http://www.geni.net/resources/rspec/3
              http://www.geni.net/resources/rspec/3/request.xsd
              http://www.geni.net/resources/rspec/ext/openflow/3
              http://www.geni.net/resources/rspec/ext/openflow/3/of-resv.xsd"
    type="request">
    
    <openflow:sliver email="user@geni.net" description="My GENI experiment" ref="http://www.geni.net">

       <openflow:controller url="tcp:myctrl.example.net:9933" type="primary" />

       <openflow:group name="mygrp">
           <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+datapath:06:a4:00:12:e2:b8:a5:d0" 
                              component_manager_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+authority+am"
                              dpid="06:a4:00:12:e2:b8:a5:d0">
             <openflow:port name="GBE0/7" num="7"/>
             <openflow:port name="GBE0/20" num="20"/>
           </openflow:datapath>


           <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+datapath:06:af:00:24:a8:c4:b9:00"  
                              component_manager_id="urn:publicid:IDN+openflow:foam:uxmal.gpolab.bbn.com+authority+am"
                              dpid="06:af:00:24:a8:c4:b9:00">
             <openflow:port name="26" num="50"/>
             <openflow:port name="47" num="71"/>
             <openflow:port name="local" num="65534"/>
           </openflow:datapath>

       </openflow:group>

       <openflow:match>
           <openflow:use-group name="mygrp" />
           <openflow:packet>
             <openflow:dl_type value="0x800" />
             <openflow:nw_src value="10.1.1.0/24" />
             <openflow:nw_proto value="6, 17" />
             <openflow:tp_src value="80" />
           </openflow:packet>
      </openflow:match>

      <openflow:match>
          <openflow:use-group name="mygrp" />
          <openflow:packet>
              <openflow:dl_type value="0x800" />
              <openflow:nw_dst value="10.1.1.0/24" />
              <openflow:nw_proto value="6, 17" />
              <openflow:tp_dst value="80" />
          </openflow:packet>
      </openflow:match>

    </openflow:sliver>

</rspec>

Note For all tags, other than <openflow:pcket>, the order of the children tags matter. Look at the specification page for details on the right order.

OpenFlowv3 vs v2 and v1 (FOAM vs Expedient)

Although OF v3 rspecs (supported by FOAM) are completely different in structure from previous Openflow rspecs (supported by Expedient), all of them basically describe the same information, so it should be straight forward, though manual, to translate from one rspec format to the other. Before starting with the conversion get familiar with the Openflow v3 rspecs by looking at examples.

If you are starting with an Expedient (v1 or v2) rspec basic guidlines are

  • replace <recv_rspec> tag with the <rspec> tag, look at the  example rspec for how this looks like.
    OPENFLOW v1-2
    <resv_rspec type="openflow">
    
          <!-- rest of rspec -->
    
    </rspec>
    
    OPENFLOW v3
    <?xml version="1.1" encoding="UTF-8"?>
    <rspec  xmlns="http://www.geni.net/resources/rspec/3"
            xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:openflow="http://www.geni.net/resources/rspec/ext/openflow/3"
            xs:schemaLocation="http://www.geni.net/resources/rspec/3
                  http://www.geni.net/resources/rspec/3/request.xsd
                  http://www.geni.net/resources/rspec/ext/openflow/3
                  http://www.geni.net/resources/rspec/ext/openflow/3/of-resv.xsd"
        type="request">
        
            <!-- rest of rspec -->
    
    </rspec>
    
  • the rest of the rspec should be inside the <openflow:sliver> tag
  • the <user>, <project>, <slice> tags do not exist anymore but some of the information there is used in the <openflow:sliver> and <openflow:controller> tags. In detail :
    • <user email> => <openflow:sliver email>
    • <project description> => <openflow:sliver description>
    • <slice contorller_url> => <openflow:controller url>
    • In <openflow:controller> tag set the type attribute as primary
      OPENFLOW v1-2
        <user affiliation="BBN" email="jane@example.net" firstname="Jane" lastname="Doe" 
              password="itsme"/>
        <project name="jane@geni" description="Jane's project at GENI"/>
        <slice controller_url="tcp:naxos.example.net:33110" name="naxos-33110" 
               description="Jane's controller."/>
      
      OPENFLOW v3
         <openflow:sliver email="jane@example.net" description="Jane's project at GENI">
            <openflow:controller url="tcp:naxos.example.net:33110" type="primary" />
            <!-- Rest of the rspc -->
         </openflow:sliver>
      
  • The <flowspace> tag is now called <openflow:match>
  • Both <port> and <switch> tags map to the <openflow:datapath> tag.
    • a switch tag corresponds to an <openflow:datapath> with no <openflow:port> tags. Just like in v1-2, an <openflow:datapath> tag with no ports implies the whole datapath. NOTE: Don't try to construct the component_id and component_manager_id attributes from your OFv1 or OFv2 rspec but copy them from the advertisement rspec. Look for the corresponding dpid and copy the necessary info into your request rspec. Actually you can copy the whole <openflow:datapath> element from your ad. rspec just make sure to remove unwanted ports.
      OPENFLOW v1-2
         <switch urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80" />
      
      OPENFLOW v3
         <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+datapath:06:d6:00:26:f1:3f:e4:80" 
                component_manager_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+authority+am" />
      
    • a port tag corresponds to an <openflow:datapath> tag with <openflow:ports>
      OPENFLOW v1-2
         <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:16"/>
         <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:18"/>
         <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:36"/>
      
      OPENFLOW v3
         <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+datapath:06:d6:00:26:f1:3f:e4:80"
                component_manager_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+authority+am" >
           <openflow:port num="16"/>
           <openflow:port num="18"/>
           <openflow:port num="36"/>
         </openflow:datapath>
      
  • the matches on the packet header tags have very similar names you just need to append openflow: before them, e.g. <dl_type> is now <openflow:dl_type>. All the packet header matches are now enclosed in an <openflow:packet> tag. Not all tags support ranges any more, but they all support lists. Check the specifications. Note: In OFv3, the <openflow:dl_type> tag only accepts hex values.
OPENFLOW v1-2
   <dl_type from="2048" to="2054"/>
   <nw_dst from="10.42.15.0" to="10.42.15.255"/>

OPENFLOW v3
   <openflow:packet>
      <openflow:dl_type value="0x800, 0x801, 0x802, 0x803, 0x804, 0x805, 0x806"/>
      <openflow:nw_dst value="10.42.15.0/24" />
   </openflow:packet>

Tips :

  • In Openflow v3 the following tags are mandatory : <openflow:sliver>, <openflow:controller>, <openflow:group>, <openflow:match>, <openflow:packet>.

<openflow:group> and <openflow:packet> can be empty in which case this means "all datapaths" and "all packets" respectively.

  • If you used to have the same ports and switches within all of your <flowspace> tags now you can create a group with the <openflow:group> tag and then use it within the <openflow:match> with an <openflow:use-group> tag
    OPENFLOW v1-2
      <flowspace>
    
        <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:16"/>
        <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:18"/>
        <port urn="urn:publicid:IDN+Example:expedient:openflow+switch:06:d6:00:26:f1:3f:e4:80+port:36"/>
        <dl_type from="2048" to="2054"/>
        <nw_dst from="10.42.15.0" to="10.42.15.255"/>
    
      </flowspace>
    
    OPENFLOW v3
     <openflow:group name="mygrp">
       <openflow:datapath component_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+datapath:06:d6:00:26:f1:3f:e4:80"         
                          component_manager_id="urn:publicid:IDN+openflow:foam:smyrna.example.net+authority+am" >
         <openflow:port num="16"/>
         <openflow:port num="18"/>
         <openflow:port num="36"/>
       </openflow:datapath>
     </openflow:group> 
    
     <openflow:match>
        <openflow:use-group name="mygrp" />
        <openflow:packet>
          <openflow:dl_type value="0x800, 0x801, 0x802, 0x803, 0x804, 0x805, 0x806"/>
          <openflow:nw_dst value="10.42.15.0/24" />
        </openflow:packet> 
     </openflow:match>
    

The best way to learn is by example:-) so here is an example conversion.

Attachments