Module Frenetic_kernel.OpenFlow

A uniform interface to OpenFlow 1.0 and 1.3.

A high-level language, such as Frenetic, should support OpenFlow 1.0 and also exploit OpenFlow 1.3 features when possible. For example, when two Frenetic actions are composed in parallel, they logically work on two copies of a packet. Certain kinds of parallel composition cannot be realized in OpenFlow 1.0, but they are trivial to implement with group tables in OpenFlow 1.3.

Similarly, OpenFlow 1.3 can implement failover efficiently using fast- failover groups. But, in OpenFlow 1.0, we have to incur a round-trip to the controller.

Instead of creating two different versions of the Frenetic compiler, we here define a high-level action data type. When targeting OpenFlow 1.0, actions translates to 1.0 action sequences and controller round-trips if needed. When targeting OpenFlow 1.3, action also builds group tables to realize actions efficiently. This requires a global analysis of all the actions in a flow table. Therefore, Frenetic needs to supply the entire flow table at once and cannot add and remove flow table entries individually

OpenFlow Identifier Types

OpenFlow requires identifiers for switches, ports, transaction numbers, etc. The representation of these identifiers varies across different versions of OpenFlow, which is why they are abstract.

type switchId = int64
val equal_switchId : switchId ‑> switchId ‑> Ppx_deriving_runtime.bool
include sig ... end
val switchId_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> switchId
val sexp_of_switchId : switchId ‑> Ppx_sexp_conv_lib.Sexp.t
val compare_switchId : switchId ‑> switchId ‑> int
type portId = int32
val equal_portId : portId ‑> portId ‑> Ppx_deriving_runtime.bool
include sig ... end
val portId_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> portId
val sexp_of_portId : portId ‑> Ppx_sexp_conv_lib.Sexp.t
val compare_portId : portId ‑> portId ‑> int
type queueId = int32
val equal_queueId : queueId ‑> queueId ‑> Ppx_deriving_runtime.bool
include sig ... end
val queueId_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> queueId
val sexp_of_queueId : queueId ‑> Ppx_sexp_conv_lib.Sexp.t
val compare_queueId : queueId ‑> queueId ‑> int
type bufferId = int32
val equal_bufferId : bufferId ‑> bufferId ‑> Ppx_deriving_runtime.bool
include sig ... end
val bufferId_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> bufferId
val sexp_of_bufferId : bufferId ‑> Ppx_sexp_conv_lib.Sexp.t
val compare_bufferId : bufferId ‑> bufferId ‑> int
exception Unsupported of string

Packet Types

type payload =
| Buffered of bufferId * Cstruct.t

(** Buffered (id, buf) is a packet buffered on a switch *)

| NotBuffered of Cstruct.t

Packet payloads

include sig ... end
val payload_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> payload
val sexp_of_payload : payload ‑> Ppx_sexp_conv_lib.Sexp.t
val payload_bytes : payload ‑> Cstruct.t

payload_bytes payload returns the bytes for the given payload

type packetInReason =
| NoMatch
| ExplicitSend
include sig ... end
val packetInReason_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> packetInReason
val sexp_of_packetInReason : packetInReason ‑> Ppx_sexp_conv_lib.Sexp.t

Switch Configuaration

type switchFeatures = {
switch_id : switchId;
switch_ports : portId list;
}

A simplification of the _switch features_ message from OpenFlow

include sig ... end
val switchFeatures_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> switchFeatures
val sexp_of_switchFeatures : switchFeatures ‑> Ppx_sexp_conv_lib.Sexp.t

Packet Forwarding

module Pattern : sig ... end
type modify =
| SetEthSrc of Packet.dlAddr
| SetEthDst of Packet.dlAddr
| SetVlan of Packet.dlVlan
| SetVlanPcp of Packet.dlVlanPcp
| SetEthTyp of Packet.dlTyp
| SetIPProto of Packet.nwProto
| SetIP4Src of Packet.nwAddr
| SetIP4Dst of Packet.nwAddr
| SetTCPSrcPort of Packet.tpPort
| SetTCPDstPort of Packet.tpPort
include sig ... end
val modify_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> modify
val sexp_of_modify : modify ‑> Ppx_sexp_conv_lib.Sexp.t
type pseudoport =
| Physical of portId
| InPort
| Table
| Normal
| Flood
| All
| Controller of int
| Local
include sig ... end
val pseudoport_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> pseudoport
val sexp_of_pseudoport : pseudoport ‑> Ppx_sexp_conv_lib.Sexp.t
type groupId = int32
include sig ... end
val groupId_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> groupId
val sexp_of_groupId : groupId ‑> Ppx_sexp_conv_lib.Sexp.t
type action =
| Output of pseudoport
| Enqueue of portId * queueId
| Modify of modify
| FastFail of groupId
include sig ... end
val action_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> action
val sexp_of_action : action ‑> Ppx_sexp_conv_lib.Sexp.t
type seq = action list
include sig ... end
val seq_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> seq
val sexp_of_seq : seq ‑> Ppx_sexp_conv_lib.Sexp.t
type par = seq list
include sig ... end
val par_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> par
val sexp_of_par : par ‑> Ppx_sexp_conv_lib.Sexp.t
type group = par list
include sig ... end
val group_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> group
val sexp_of_group : group ‑> Ppx_sexp_conv_lib.Sexp.t
type timeout =
| Permanent

(** No timeout *)

| ExpiresAfter of Packet.int16

(** Time out after n seconds *)

include sig ... end
val timeout_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> timeout
val sexp_of_timeout : timeout ‑> Ppx_sexp_conv_lib.Sexp.t
type flow = {
pattern : Pattern.t;
action : group;
cookie : int64;
idle_timeout : timeout;
hard_timeout : timeout;
}
include sig ... end
val flow_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> flow
val sexp_of_flow : flow ‑> Ppx_sexp_conv_lib.Sexp.t
type flowTable = flow list

Priorities are implicit

include sig ... end
val flowTable_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> flowTable
val sexp_of_flowTable : flowTable ‑> Ppx_sexp_conv_lib.Sexp.t
type flowStats = {
flow_table_id : int64;
flow_pattern : Pattern.t;
flow_actions : action list;
flow_duration_sec : int64;
flow_duration_nsec : int64;
flow_priority : int64;
flow_idle_timeout : int64;
flow_hard_timeout : int64;
flow_packet_count : int64;
flow_byte_count : int64;
}

The body of a reply to an individual flow statistics request

include sig ... end
val flowStats_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> flowStats
val sexp_of_flowStats : flowStats ‑> Ppx_sexp_conv_lib.Sexp.t
type portStats = {
port_no : int64;
port_rx_packets : int64;
port_tx_packets : int64;
port_rx_bytes : int64;
port_tx_bytes : int64;
port_rx_dropped : int64;
port_tx_dropped : int64;
port_rx_errors : int64;
port_tx_errors : int64;
port_rx_frame_err : int64;
port_rx_over_err : int64;
port_rx_crc_err : int64;
port_collisions : int64;
}
include sig ... end
val portStats_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> portStats
val sexp_of_portStats : portStats ‑> Ppx_sexp_conv_lib.Sexp.t
type event =
| SwitchUp of switchId * portId list
| SwitchDown of switchId
| PortUp of switchId * portId
| PortDown of switchId * portId
| PacketIn of string * switchId * portId * payload * int * packetInReason
| PortStats of switchId * portStats
| FlowStats of switchId * flowStats
type pktOut = payload * portId option * action list
include sig ... end
val pktOut_of_sexp : Ppx_sexp_conv_lib.Sexp.t ‑> pktOut
val sexp_of_pktOut : pktOut ‑> Ppx_sexp_conv_lib.Sexp.t
val format_list : 'a list ‑> to_string:('a ‑> string) ‑> string
val format_action : Format.formatter ‑> action ‑> unit
val format_seq : Format.formatter ‑> seq ‑> unit
val format_par : Format.formatter ‑> par ‑> unit
val format_group : Format.formatter ‑> group ‑> unit
val format_flow : Format.formatter ‑> flow ‑> unit
val format_flowTable : Format.formatter ‑> flowTable ‑> unit
val string_of_action : action ‑> string
val string_of_seq : seq ‑> string
val string_of_par : par ‑> string
val string_of_flow : flow ‑> string
val string_of_group : group ‑> string
val string_of_flowTable : ?⁠label:string ‑> flowTable ‑> string
val string_of_event : event ‑> string
module OF10 = Frenetic_kernel.OpenFlow0x01
module To0x01 : sig ... end
module From0x01 : sig ... end