OpenFlowMPLS Implementation

From OpenFlow Wiki

Jump to: navigation, search

Contents

Introduction

The MPLS-extension of the OpenFlow specification has been incorporated into the baseline OpenFlow source code. The OpenFlow library, the reference controller and reference switch, as well as the NetFPGA installation has been modified to support the MPLS extension.

At the moment the modification is available for the OpenFlow 0.8.9 and 1.0 versions. Due to the current limitations in OpenFlow packaging, the modified sources are distributed in tarballs.

OpenFlow library

The following changes were made to the OpenFlow common library.

Flow table

To enable the MPLS support, the switch must be able to match MPLS lables in its flow table.

There are many common scenarios, where a packet will need to match on two or more labels; for example in case of an egress traffic to an MPLS tunnel. Ideally this could be supported with a match on one label at a time, and then sending the packet back to the flow table (allowing additional matches). However, in the vast majority of real life MPLS use cases at most two labels are involved. Therefore the chosen method for supporting was to allow matcing on up to two MPLS labels at once in the flow table.

To enable matching on one or two labels, the flow table entries had to be extended with two additional fields:

struct ofp_match 
{
    uint32_t wildcards;           /* Wildcard fields. */
    uint16_t in_port;             /* Input switch port. */
    uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
    uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
    uint16_t dl_vlan;             /* Input VLAN. */
    uint16_t dl_type;             /* Ethernet frame type. */
    uint8_t nw_proto;             /* IP protocol. */
    uint8_t pad;                  /* Align to 32-bits. */
    uint32_t nw_src;              /* IP source address. */
    uint32_t nw_dst;              /* IP destination address. */
    uint16_t tp_src;              /* TCP/UDP source port. */
    uint16_t tp_dst;              /* TCP/UDP destination port. */
    uint32_t mpls_label1          /* Top MPLS label on stack. */
    uint32_t mpls_label2;         /* Second MPLS label (if available). */
};

Wildcarding the MPLS labels is also enabled by defining the following two flags:

  OFPFW_MPLS_L1	= 1 << 21, /* MPLS Label 1. */
  OFPFW_MPLS_L2	= 1 << 22, /* MPLS label 2. */


Flow table actions

Output action

The output action is used to send packets out on a physical or virtual port already in OpenFlow (e.g. OFPP_FLOOD, OFPP_CONTROLLER, OFPP_NONE). This action has been expanded so that it can be used to send packets to the virtual port table as well. The original 16-bit output action port field has been expanded to 32-bits to support the new port space:

0x00000000 – 0x0000ff00: physical ports
0x0000ff01 – 0x0000fff8: unused
0x0000fff9 – 0x0000ffff: virtual ports (OpenFlow)
0x00010000 – 0x40000000: virtual ports

The new output action is defined as:

struct ofp_action_output {
    uint16_t type;                  /* OFPAT_OUTPUT. */
    uint16_t len;                   /* Length is 8. */
    // port space is now 32-bits to accomodate virtual ports
    uint32_t port;                  /* Output port. */
    uint16_t max_len;               /* Max length to send to controller. */
    uint8_t  pad[6];                /* Padding. */
};

Rewrite MPLS Label Action

Since the current version of OpenFlow includes a separate action to rewrite each of the fields which can be matched, a new rewrite action has also been included for the MPLS label field. This action will replace only the 20-bit label for the top label on the label stack with the value specified. It could be used to implement a swap action but this action will, of course, not handle decrementing the MPLS TTL field.

struct ofp_action_mpls_label {
    uint16_t type;                  /* OFPPAT_SET_MPLS_LABEL. */
    uint16_t len;                   /* Length is 8. */
    uint32_t label_out; 	      /* outgoing mpls label. */
};

Rewrite MPLS EXP Action

OpenFlow supports an action to rewrite the VLAN PCP bits even though a switch cannot match on this field. Similarly, an action has been included to rewrite the MPLS EXP bits even though the switch is not able not match on this field.

struct ofp_action_mpls_exp {
    uint16_t type;                  /* OFPPAT_SET_MPLS_EXP. */
    uint16_t len;                   /* Length is 8. */
    uint8_t	exp;		      /* experimental/class of service bits */
    uint8_t pad[3];
};

Ericsson Extensions

In order to support MPLS, the only requirement at the flow table is the ability to forward to a virtual port. However, it is expected that, for efficiency, some switch implementations will want to perform some of the MPLS related actions at the flow table. As a result, all of the MPLS related actions available at the virtual port table will also be available at the flow table.

Since the flow table in OpenFlow was not intended to support these type of actions, they should be completely optional and so they had been included separately in the library as Ericsson extensions.

These extensions can be found in the ericsson-ext.h header file:

Ericsson Vendor ID:

#define ER_VENDOR_ID 0x000001EC

Ericsson flow table actions structure:

/* Header for Ericsson-defined actions
 * Note that this is effectively an extension/subclass
 * of ofpat_action_vendor_header defined in include/openflow/openflow.h */
struct er_action_header 
{
    uint16_t type;                  /* OFPAT_VENDOR. */
    uint16_t len;                   /* Length is 16. */
    uint32_t vendor;                /* ER_VENDOR_ID. */
    uint16_t subtype;               /* Ericsson action type (er_action_type) */
    uint8_t pad[6];                 /* align to 64-bit boundary */
};

The currently defined Ericsson actions:

enum er_action_type 
{
    ERXT_POP_MPLS,		/* Pop an MLPS label.  */
    ERXT_PUSH_MPLS, 		/* Push an MPLS label. */
};

MPLS pop action structure:

/* Action structure for ERXT_POP_MPLS. */
struct er_action_pop_mpls 
{
    struct er_action_header erah;
    struct action_pop_mpls apm;
};

MPLS push action structure:

/* Action structure for ERXT_PUSH_MPLS. */
struct er_action_push_mpls 
{
    struct er_action_header erah;
    struct action_push_mpls apm;
};

Note that the action_pop_mpls and action_push_mpls structs are defined in the virtual port table actions section.

Virtual Port Table

The major change to OpenFlow is the addition of a Virtual Port Table, which is described on the OpenFlowMPLS_Description page.

The following changes were made to the baseline OpenFlow header to handle virtual port table entries.

struct ofp_vport_mod 
{
    struct ofp_header header;
    uint32_t vport;      	    /* virtual port number. */
    uint32_t parent_port; 	    /* parent port number */
    /* Flow actions. */
    uint16_t command;             /* One of OFPFC_*. */
    uint8_t pad[6];               /* Align to 32-bits. */
    //uint32_t reserved;          /* Reserved for future use. */
    struct ofp_action_header actions[0]; /* Uses the same action header
                                         as the flow-table.
                                         The action length is inferred
                                         from the length field in the
                                         header. */
};

The above structure defines the message to add or remove a virtual port table entry. It is similar in nature to adding a flow table entry. A virtual port and a command (add or remove) must be specified as well as a list of actions to be associated with the virtual port table entry. The parent_port indicates the parent port of this virtual port table entry.

enum ofp_vport_mod_command
{
    OFPVP_ADD,		/* New virtual port. */
    OFPVP_DELETE		/* Delete virtual port. */
};

Virtual Port Table Actions

Supported virtual port table actions:

enum ofp_vport_action_type {
    OFPPAT_OUTPUT,   			/* Output to switch port. 	*/
    OFPPAT_POP_MPLS,     		/* Pop MLPS label. 		*/
    OFPPAT_PUSH_MPLS,     		/* Push MPLS label. 		*/
    OFPPAT_SET_MPLS_LABEL,		/* Rewrite MPLS label. 		*/
    OFPPAT_SET_MPLS_EXP,		/* Rewrite MPLS exp bits.	*/
    OFPPAT_VENDOR = 0xffff		/* not yet supported. 		*/
};

Pop MPLS action

MPLS Pop action structure:

struct ofp_vport_action_pop_mpls
{
    uint16_t type;                  /* OFPPAT_POP_MPLS. */
    uint16_t len;                   /* Length is 8. */
    struct action_pop_mpls apm;
    uint8_t pad[4];
};

Action structure with parameters for pop mpls:

struct action_pop_mpls 
{
    uint16_t eth_type;		/* eth_type of packet 	*/
    uint8_t flags;		/* MPLS_POP_* flags	*/
    uint8_t pad[5];		/* align to 64-bits	*/
};

The flags for the MPLS pop action are defined as:

enum {
     MPLS_POP_DONT_POP	= 1 << 0, 	/* Don't pop. */
     MPLS_POP_DECREMENT_TTL	= 1 << 1,	/* Decrement the ttl. */
     MPLS_POP_COPY_TTL	= 1 << 2,	/* Copy the ttl bits to the next header. */
     MPLS_POP_COPY_EXP	= 1 << 3	/* Copy the exp bits to the next header. */
};

The DECREMENT_TTL flag indicates that the time to live value of the label to be popped should be decremented. Note that this action will not deal with TTL expired exceptions. The COPY_TTL flag causes the TTL value of the popped label to be copied to the next label in the label stack, or back to the IP header if the stack is empty. Similarly, the COPY_EXP flag causes the EXP bits to be copied to the next MPLS label or over the ToS bits in the IP Header. Finally, if the DONT_POP flag is set, the label is not popped. This enables decrementing the TTL when swapping an MPLS label (since swapping does not decrement the TTL field).

Push MPLS action

MPLS Push action structure:

struct ofp_vport_action_push_mpls
{
   uint16_t type;                  /* OFPAT_OFPPAT_PUSH_MPLS. */
   uint16_t len;                   /* Length is 8. */
   struct action_push_mpls apm;
   uint8_t pad[4];
};

Action structure with parameters for push mpls:

struct action_push_mpls
{
   uint32_t label_out;	/* outgoing mpls label.	*/
   uint8_t exp;		/* exp/cos bits. 	*/
   uint8_t ttl;		/* time to live. 	*/
   uint8_t flags;		/* MPLS_PUSH_* flags	*/
   uint8_t pad[1];		/* align to 64-bits 	*/
};

The flags for the MPLS push action are defined as:

enum {
   MPLS_PUSH_DECREMENT_TTL	= 1 << 0,	/* Decrement the ttl. */
   MPLS_PUSH_TTL_NEXT	= 1 << 1,	/* Copy the ttl bits from the next header. */
   MPLS_PUSH_EXP_NEXT	= 1 << 2,	/* Copy the exp bits from the next header. */
   MPLS_PUSH_TTL_PREV	= 1 << 3,	/* Copy the ttl bits from the previous label.*/
   MPLS_PUSH_EXP_PREV	= 1 << 4	/* Copy the exp bits from the previous label. */
};

The DECREMENT_TTL flag allows the ttl field to be decremented on the label being pushed. When the TTL_NEXT field is set the TTL bits for the label to be pushed are taken from the next MPLS label, or from the IP header if the label stack is empty. In contrast, the TTL_PREV flag causes the TTL bits for the label to be pushed to come from the last label that was popped. This can be used for implementing a swap using a pop followed by a push.

The same cases apply for the EXP bits where the EXP_NEXT and EXP_PREV flags are used.

Rewrite MPLS Label Action

The MPLS-related rewrite actions are supported on the virtual port table as well.

// Header for the rewrite MPLS label action: 

struct ofp_vport_action_set_mpls_label
{
    uint16_t type; 			/* OFPPAT_SET_MPLS_LABEL. */
    uint16_t len; 			/* Length is 8. */
    uint32_t label_out; 		/* outgoing mpls label. */
};

Rewrite MPLS Exp Bits Action

// Header for rewrite MPLS exp bits action: 

struct ofp_vport_action_set_mpls_exp
{
    uint16_t type;                  /* OFPPAT_SET_MPLS_EXP. */
    uint16_t len;                   /* Length is 8. */
    uint8_t	exp;                  /* experimental/class of service bits */
    uint8_t pad[3];
};

TTL Exceptions

Handling the TTL field in the MPLS label is non-trivial with OpenFlow. While the IPv4 header also has a TTL field, there is currently no way to decrement it or manage the TTL expired action. While the Push and Pop MPLS actions include the functionality to decrement the TTL field, handling the TTL exception is non-trivial as it requires the actions to support conditional logic.

Therefore it has to be assumed that the MPLE-enabled OpenFlow switch will autonomously handle TTL expiry. Nevertheless, an mpls_ttl0_dropped has been added to the ofp_port_stats message to keep track of the number of packets that have been dropped due to the MPLS TTL expired exception.

Statistics

Statistics for virtual ports are requested the same way as statistics for physical ports: by using an ofp_stats_req message with the type field set to OFPST_PORT. Virtual ports use the same ofp_port_stats structure as physical ports. Only the tx_packets and tx_bytes fields are returned for virtual ports however (as the rest of the fields are unsupported).

Requesting port statistics has been changed. Previously when requesting statistics for a port (OFPST_PORT), the message body was empty and there was no way to specify which ports the statistics should be returned for. Now the body of the message contains a list of 32-bit port numbers for which switch should return statistics for. The number of port numbers requested is implicit: it is inferred from the length of the message.

Statistics can also be requested for the virtual port table using the ofp_stats_req message. The body will be empty and a new type field has been defined:

enum ofp_stats_types {
    ...
    OFPST_PORT_TABLE,
    ...      
};

The return message for the virtual port table statistics will use the structure below.

struct ofp_vport_table_stats {
    uint32_t max_vports;         /* Max number of entries supported */
    uint32_t active_vports;      /* Number of active entries */
    uint64_t lookup_count;       /* Number of lookups performed */
    uint64_t port_match_count;   /* Number of entries matched in vport table */
    uint64_t chain_match_count;  /* Number of entries accessed by chaining */
};

The lookup_count field is the number of packets that have been looked up against the virtual port table. The port_match_count is the number of virtual port entries that have matched the lookups. When a virtual port has a parent, accessing the parent virtual port entry increments the chain_match_count.

Handshake Messages

When the switch responds to the features request message, the reply includes a bitmap of capabilities. This bitmap has been extended to include two new capabilities.

enum ofp_capabilities {
    OFPC_FLOW_STATS     = 1 << 0,  /* Flow statistics. */
    OFPC_TABLE_STATS    = 1 << 1,  /* Table statistics. */
    OFPC_PORT_STATS     = 1 << 2,  /* Port statistics. */
    OFPC_STP            = 1 << 3,  /* 802.1d spanning tree. */
    OFPC_MULTI_PHY_TX   = 1 << 4,  /* Supports transmitting through multiple
                                      physical interfaces */
    OFPC_IP_REASM       = 1 << 5,  /* Can reassemble IP fragments. */
    OFPC_VPORT_TABLE    = 1 << 6,  /* Supports a virtual port table 
                                      rest of virtual port table attributes
                                      specified in ofp_vport_table_features */
    OFPC_MPLS_ENABLED	 = 1 << 7    /* Switch is MPLS-enabled. */
};

The OFPC_VPORT_TABLE, indicates the switch supports a virtual port table. The OFPC_MPLS_ENABLED indicates the switch is MPLS enabled which means that it can match two MPLS labels at the flow table and supports the rewrite MPLS label and MPLS EXP bits as actions at the flow table.

If the switch supports a virtual port table, the controller will send a separate message to the switch to determine which actions are supported at the virtual port table. This message simply consists of the ofp_header with the type set to OFPT_FEATURES_REQUEST. The switch replies with the ofp_vport_table_features message, defined below:

struct ofp_vport_table_features {
    struct ofp_header header;
    uint32_t max_vports;          /* Max number of entries supported */
    uint32_t actions;             /* Bitmap of supported port table actions */
    uint8_t mixed_chaining;       /* 0 = false, 1 = true */
    uint8_t pad[5];		    /* align to 64-bits */
};

The actions field is a bitmap of supported actions at the virtual port table and these are currently defined to be:

enum ofp_vport_action_type {
    OFPPAT_OUTPUT,	   		/* Output to switch port .	*/
    OFPPAT_POP_MPLS,       		/* Pop MLPS label. 		*/
    OFPPAT_PUSH_MPLS,      		/* Push MPLS label. 		*/
    OFPPAT_REWRITE_MPLS_LABEL,	/* Rewrite MPLS label. 		*/
    OFPPAT_REWRITE_MPLS_EXP,		/* Rewrite MPLS exp bits.	*/
};

The max_vports field indicates the maximum allowed number of virtual port table entries. This can also be found in the vport_table_stats message. The mixed_chaining field is used to indicate whether virtual ports with different actions can be mixed together. This is needed because the NetFPGA implementation cannot support chaining a virtual port table entry that performs a pop action to one that performs a push.

Note that at present these are mostly related to supporting MPLS. In the future this would need to be replaced with a more general list where protocol/vendor specific actions could be specified in a fashion similar to vendor extensions for actions at the flow table. Also note that a supported action is OFPPAT_OUTPUT which allows a copy of the packet to be sent to a virtual or physical port. The original copy of the packet will be processed through the chain of virtual ports until the parent_port at the virtual port table entry is a physical port or one of the originally defined virtual ports (e.g. OFPP_IN_PORT, OFPP_NONE).


Control Plane

There are many possible directions to take in managing the control plane for the MPLS extension project. For example one could provide a controller that could inter-operate with existing MPLS networks by supporting various LDP (Label Distribution Protocol) protocols and exchange LDP messages on behalf of the switches it controls. For now we have chosen to provide a simple controller that can configure an OpenFlow switch to reflect the forwarding state of an MPLS-switch that has been statically specified in a file. An abstract representation of the controller is shown on the following figure.

Simple MPLS Controller

A simple abstract representation of the controller is shown above. The controller runs a logical MPLS switch for every MPLS-enabled OpenFlow switch it controls. This logical switch instance has its forwarding information populated from an externally supplied file. The controller determines the switch's capabilities during the initial handshake phase. The controller then uses the capabilities of the switch to determine how to translate the switch's forwarding information (FIB) into OpenFlow messages.

MPLS FIB

The format of the forwarding information of an MPLS switch is dependant on the implementation but the FIB includes two tables:

  • FTN (FEC To NHLFE) Table:
    • Used for unlabeled packets
    • Maps FECs (Forwarding Equivalence Class) to NHLFE entries
    • We define the FEC to match the original OpenFlow 10 tuple
  • ILM (Incoming Label Map) Table:
    • Used for labeled packets
    • Maps labels for incoming packets to NHLFE entries

NHLFE (Next Hop Label Forwarding Entry):

  • Specifies the action the switch should take
  • E.g. push a label, pop label stack, etc

XML FIB File

As the XML file format is quite simple, we give you an example, instead of providing a schema definition file:

  <?xml version="1.0"?>
  <mpls:MPLS_FIB xmlns:mpls="mpls">
        <!-- Define one FEC to NHFLE Table -->
        <mpls:FTN_Table>

                <!-- Define as many FTN Table entires as you want -->
		<mpls:FTN>
			<!-- FEC is defined to be the OpenFlow 10 tuple-->
			<!-- omitting a field will result in it being wildcarded -->
			<mpls:in_port>0</mpls:in_port>
			<mpls:dl_src>00:1a:4b:53:f7:2c</mpls:dl_src>
			<mpls:dl_dst>00:1a:4b:53:f7:2c</mpls:dl_dst>
			<mpls:dl_vlan>0</mpls:dl_vlan>
			<mpls:dl_type>2048</mpls:dl_type>
			<mpls:nw_proto>17</mpls:nw_proto>
			<!-- IP addresses specified in standard dotted decimal notation -->
			<mpls:nw_src>10.0.0.2/30</mpls:nw_src>
			<mpls:nw_dst>10.0.0.1</mpls:nw_dst>
			<mpls:tp_src>3840</mpls:tp_src>
			<mpls:tp_dst>3840</mpls:tp_dst>

			<mpls:NHLFE>
				<!-- Currently each NHLFE entry can have one action -->
				<!-- MPLS push action -->
				<mpls:push>
					<!-- send packet out this port -->
					<mpls:out_port>1</mpls:out_port>
					<!-- rewrite the src & dst MAC addresses -->
					<mpls:src_mac>11:22:33:00:00:00</mpls:src_mac>
					<mpls:dst_mac>66:77:88:00:00:01</mpls:dst_mac>
					<!-- push this MPLS label -->
					<mpls:mpls_label>768</mpls:mpls_label>
				</mpls:push>
			</mpls:NHLFE>
		</mpls:FTN>

	</mpls:FTN_Table>

	<!-- Define one Incoming Label Map Table -->
	<mpls:ILM_Table>

		<!-- Define as many ILM Table entries as you like -->
		<mpls:ILM>
			<mpls:in_port>0</mpls:in_port>
			<mpls:mpls_label>256</mpls:mpls_label>

			<mpls:NHLFE>
				<mpls:pop>
					<mpls:out_port>2</mpls:out_port>
					<mpls:src_mac>11:22:33:00:00:00</mpls:src_mac>
					<mpls:dst_mac>66:77:88:00:00:02</mpls:dst_mac>
				</mpls:pop>
			</mpls:NHLFE>

		</mpls:ILM>

		<mpls:ILM>
			<mpls:in_port>1</mpls:in_port>
			<mpls:mpls_label>512</mpls:mpls_label>

			<mpls:NHLFE>
				<!-- MPLS swap action -->
				<mpls:swap>
					<mpls:mpls_label>768</mpls:mpls_label>
					<mpls:out_port>1</mpls:out_port>
					<mpls:src_mac>11:22:33:00:00:01</mpls:src_mac>
					<mpls:dst_mac>66:77:88:00:00:01</mpls:dst_mac>
				</mpls:swap>
			</mpls:NHLFE>

		</mpls:ILM>

	</mpls:ILM_Table>
  </mpls:MPLS_FIB>

Limitations

  • Currently for each switch the controller simply reads the MPLS FIB file, sends the OpenFlow messages to configure the switch appropriately and then sits idle. While the controller has the logic to remove and query statistics for the flow table and virtual port table entries that it installs, this is not currently being used.
  • The OpenFlow-MPLS controller currently does not support usage scenarios involving matching on multiple labels. While the datapath supports matching on 2 labels in all of our implementations, it isn't clear how this would be represented in the FIB. In scenarios that involve matching on more than one label, real MPLS switches perform multiple lookups but our OpenFlow switches match on up to 2 labels at once. This means the controller may have to merge the forwarding information from more than one FIB entry into a Flow table entry and we currently do not support this.
  • Currently only one NHLFE entry can be specified per FTN or ILM entry.

Overview of Source Files

The source for the controller can be found under downloads. Note that this code requires the libxml2 library. The code is commented heavily with all the changes to existing files encapsulated in comment blocks that start with // MAH: start and end with // MAH: end. The following provides an overview of the files that have been added/modified for the simple MPLS controller.

  • controller/controller.c
    The simple controller has been modified. If the pre-compiler macro MPLS_CONTROLLER is defined, then the controller will instantiate an mpls_switch instance rather than the default l_switch (Ethernet learning switch) instance for each new OpenFlow switch.
  • lib/freelist.{c,h}
    A freelist data structure used by the controller to manage the virtual port space for a switch.
  • lib/mpls-fib.{c,h}
    Defines the data structures for the MPLS forwarding information as well as the functionality to translate this information into OpenFlow messages.
  • lib/mpls-switch.{c,h}
    Effectively a stripped down version of learning-switch.{c,h}, this defines is a logical representation for an MPLS switch that the controller instantiates to manage an MPLS-enabled OpenFlow switch.
  • lib/read-mpls.{c,h}
    Reads the MPLS forwarding information (FIB) from an XML file using the libxml2 library.
  • lib/vconn-mpls.{c,h}
    Defines functions to add or remove flow table and virtual port table entries needed to configure an MPLS-enabled OpenFlow switch.
  • controller/example_mpls_fib.xml
    Is an example MPLS FIB file as described above.

Software switch

The switches implement everything described in OpenFlowMPLS_Description. More details can be found in the code which has been extensively commented and is available in the downloadable tarballs. The software switch, as well as the other components is available for the OpenFlow 0.8.9 and 1.0.0 versions

Under utilities there is a new mpls_pkt_gen directory. This is an extremely simple utility that uses raw sockets to generate hardcoded MPLS packets which can be used for testing.

User-space switch

This section provides a brief overview of the changes to the original OpenFlow user-space switch implementation.

Limitations

  • TTL Handling: part of the implicit behaviour of an MPLS-enabled OpenFlow switch is to handle TTL-expired exceptions. Currently any labeled packet that enters with a TTL of 1 or less will be dropped. A mpls_ttl0_dropped counter has been added on each port to keep track of the number of MPLS packets that have been dropped due to the TTL expired exception. This counter is part of the ofp_port_stats message

User-space files

Changes to the code in existing files have been encapsulated by a comment block beginning with "MAH: start" and ending with "MAH: end".

Overview of added files:

  • switch/er_act.{c,h}
    This file is for Ericsson extensions. The pop_mpls & push_mpls actions are supported at the flow table as Ericsson extensions in this implementation.
  • switch/pt_act.{c,h}
    Similar to how dp_act.{c,h} contains the code to support actions at the flow table, pt_act contains the code to support actions at the virtual port table.
  • switch/switch_port.{c,h}
    This defines the virtual port table and all its operations.
  • lib/red-black-tree.{c,h}
    Since we let the software switch implementation support billions of virtual port table entries, we use a red-black tree to manage virtual port table entries.
  • lib/stack.{c,h}
    Used by the red-black-tree implementation mentioned above.
  • lib/misc.{c,h}
    Also used by the red-black tree implementation mentioned above.


Kernel-space switch

This section provides a brief overview of the changes to the baseline OpenFlow kernel-space switch implementation. The changes to the kernel-space switch are for the most part identical as the changes to the user-space switch. Much of the code used in user-space, however, had to be adapted to use kernel memory management and to work with sk_buff rather than ofpbuf packet buffer structures.

Limitations

  • TTL Handling: part of the implicit behaviour of an MPLS-enabled OpenFlow switch is to handle TTL-expired exceptions. Currently any labeled packet that enters with a TTL of 1 or less will be dropped. A mpls_ttl0_dropped counter has been added on each port to keep track of the number of MPLS packets that have been dropped due to the TTL expired exception. This counter is part of the ofp_port_stats message
  • The skb is typically allocated with a limited amount of headroom (between 18-22 bytes). Thus there is only room to push 4-5 labels at once.

Kernel-space files

Overview of added files:

  • datapath/er_act.{c,h}
    This file is for Ericsson extensions. The pop_mpls & push_mpls actions are supported at the flow table as Ericsson extensions in this implementation.
  • datapath/pt_act.{c,h}
    Similar to how dp_act.{c,h} contains the code to support actions at the flow table, pt_act contains the code to support actions at the virtual port table.
  • datapath/switch_port.{c,h}
    This defines the virtual port table and all its operations.
  • datapath/kred-black-tree.{c,h}
    This file was adapted from lib/red-black-tree.{c,h} to work in kernel space.
  • datapath/kstack.{c,h}
    This file was adapted from lib/kstack.{c,h} to work in kernel space.
  • datapath/kmisc.{c,h}
    This file was adapted from lib/kmisc.{c,h} to work in kernel space.


Note: All the changes to the code have been encapsulated by a comment block beginning with "MAH: start" and ending with "MAH: end".

NetFPGA implemenattion

The NetFPGA implementation was also extended with MPLS support for OpenFlow 0.8.9 and 1.0.0. This requires modifications to the kernel space switch as well. The modifications include changing the files under hwtable_nf2 directory (the hardware table) and files in the datapath directory.

For general information on the NetFPGA (including its design and its limitations), please visit the NetPGA wiki page

Running The Code

Please follow these steps if you want to use the NetFPGA implementation:

  • Get a copy the Verilog code and the bit file for the NetFPGA design as well as the kernel module from the downloads.
  • Follow the original instructions for compiling the kernel module.

In brief you need to execute the following commands:

> unpack openflow-mpls.tgz that you downloaded above
> cd into the directory
> ./configure --with-l26=/lib/modules/`uname -r`/build --enable-hw-tables=nf2
> make
> make install
  • Load the bitfile into the NetFPGA
sudo nf2_download openflow_MPLS_switch2.bit
  • insmode the openflow kernel module and the hardware table from datapath/linux-2.6/
sudo /sbin/insmod openflow_mod.ko
sudo /sbin/insmod hwtable_nf2_mod.ko
  • setup the openflow switch with 4 ports (nf2cX ports) on the machine using dptcl. a sample script can be found at utilities/setup.sh.

Make sure that you have at least a two port NIC in the host, and nf2c0 connected to eth1, and nf2c1 connected to eth2.

  • run controller from the controller directory:
  sudo ./controller -v ptcp:2525
  • run secchan from the secchan directory
  sudo ./secchan --fail=closed nl:0 tcp:hostaddr:2525

Note: replace hostaddr with localhost if you are running everything on one box.

  • now the controller will ask for its input fib file. provide a file like simple_nf2.xml from the controller directory.
  • Now the controller has loaded the NetFPGA with entries (Flow table and Virtual port table entries) to do the actions specified at the fib xml file. You can generate MPLS packets using a simple program available at utilities/mpls_pkt_gen.

Utilities

Wireshark dissector

The downloadable tarball contains a wireshark dissector, which enables tracing MPLS OpenFlow messages.

The dissector can be found under /utilities/wireshark_dissectors.

Downloads

OpenFlow 0.8.9

File:Openflow 089 mpls.ppt Change the .ppt extension to .tgz after download!

This version is based on Mart's 0.8.9 MPLS implementation, with bugfixes, and the addition of the wireshark dissector.

The NetFPGA Verliog code and bitfile can be downloaded separately from the NetFPGA wiki.

OpenFlow 1.0

File:Openflow 100 mpls.ppt Change the .ppt extension to .tgz after download!

This version is based on Neda's port of Mart's MPLS impementation to 1.0.0, with the addition of the MPLS enabled wireshark dissector.

People

  • Neda Beheshti
  • Mart Haitjema
  • Peyman Kazemian