Skip to content

Commit

Permalink
Introduce OpenFlow::Message super class of OF messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
yasuhito committed Jul 6, 2015
1 parent 2244eec commit 87793a1
Show file tree
Hide file tree
Showing 23 changed files with 142 additions and 265 deletions.
2 changes: 1 addition & 1 deletion Rakefile
@@ -1,7 +1,7 @@
require 'bundler/gem_tasks'

RELISH_PROJECT = 'trema/pio'
FLAY_THRESHOLD = 609
FLAY_THRESHOLD = 1547

task default: :travis
task test: [:spec, :cucumber]
Expand Down
2 changes: 1 addition & 1 deletion features/open_flow13/echo_reply.feature
Expand Up @@ -115,4 +115,4 @@ Feature: Pio::Echo::Reply

Scenario: parse error
When I try to parse a file named "open_flow10/features_request.raw" with "Pio::Echo::Reply" class
Then it should fail with "Pio::ParseError", "Invalid Echo Reply 1.3 message."
Then it should fail with "Pio::ParseError", "Invalid Echo Reply message."
2 changes: 1 addition & 1 deletion features/open_flow13/echo_request.feature
Expand Up @@ -115,4 +115,4 @@ Feature: Pio::Echo::Request

Scenario: parse error
When I try to parse a file named "open_flow10/features_request.raw" with "Pio::Echo::Request" class
Then it should fail with "Pio::ParseError", "Invalid Echo Request 1.3 message."
Then it should fail with "Pio::ParseError", "Invalid Echo Request message."
2 changes: 1 addition & 1 deletion features/open_flow13/features_reply.feature
Expand Up @@ -50,4 +50,4 @@ Feature: Pio::Features::Reply

Scenario: parse error
When I try to parse a file named "open_flow10/echo_request.raw" with "Pio::Features::Reply" class
Then it should fail with "Pio::ParseError", "Invalid Features Reply 1.3 message."
Then it should fail with "Pio::ParseError", "Invalid Features Reply message."
2 changes: 1 addition & 1 deletion features/open_flow13/features_request.feature
Expand Up @@ -86,4 +86,4 @@ Feature: Pio::Features::Request

Scenario: parse error
When I try to parse a file named "open_flow10/hello.raw" with "Pio::Features::Request" class
Then it should fail with "Pio::ParseError", "Invalid Features Request 1.3 message."
Then it should fail with "Pio::ParseError", "Invalid Features Request message."
2 changes: 2 additions & 0 deletions lib/pio/open_flow.rb
Expand Up @@ -17,5 +17,7 @@ module OpenFlow
require 'pio/open_flow/datapath_id'
require 'pio/open_flow/flags'
require 'pio/open_flow/format'
require 'pio/open_flow/message'
require 'pio/open_flow/open_flow_header'
require 'pio/open_flow/phy_port'
require 'pio/open_flow/port_number'
23 changes: 23 additions & 0 deletions lib/pio/open_flow/message.rb
@@ -0,0 +1,23 @@
module Pio
module OpenFlow
# OpenFlow messages.
class Message
def self.inherited(child)
child.class_eval <<-EOS
def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
message_name = name.split('::')[1..-1].join(' ')
raise Pio::ParseError, "Invalid \#{message_name} message."
end
EOS
end

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end
end
end
30 changes: 2 additions & 28 deletions lib/pio/open_flow10/echo.rb
@@ -1,12 +1,10 @@
require 'forwardable'
require 'pio/open_flow'
require 'pio/open_flow10/message'

module Pio
# OpenFlow 1.0 Echo Request and Reply message.
module Echo
# OpenFlow 1.0 Echo Request message.
class Request
class Request < OpenFlow::Message
# OpenFlow 1.0 Hello message
class Format < BinData::Record
extend OpenFlow::Format
Expand All @@ -19,27 +17,15 @@ def user_data
end
end

def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
raise Pio::ParseError, 'Invalid Echo Request message.'
end

def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = user_options[:body] || user_options[:user_data] || ''
@format = Format.new(header: header_options, body: body_options)
end

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end

# OpenFlow 1.0 Echo Reply message.
class Reply
class Reply < OpenFlow::Message
# OpenFlow 1.0 Hello message
class Format < BinData::Record
extend OpenFlow::Format
Expand All @@ -52,23 +38,11 @@ def user_data
end
end

def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
raise Pio::ParseError, 'Invalid Echo Reply message.'
end

def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = user_options[:body] || user_options[:user_data] || ''
@format = Format.new(header: header_options, body: body_options)
end

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end
end
end
30 changes: 2 additions & 28 deletions lib/pio/open_flow10/features.rb
@@ -1,12 +1,10 @@
require 'forwardable'
require 'pio/open_flow'
require 'pio/open_flow10/message'

module Pio
# OpenFlow 1.0 Features Request and Reply message.
class Features
# OpenFlow 1.0 Features Request message.
class Request
class Request < OpenFlow::Message
# OpenFlow 1.0 Features Request message
class Format < BinData::Record
extend OpenFlow::Format
Expand All @@ -19,27 +17,15 @@ def user_data
end
end

def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
raise Pio::ParseError, 'Invalid Features Request message.'
end

def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = user_options[:body] || user_options[:user_data] || ''
@format = Format.new(header: header_options, body: body_options)
end

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end

# OpenFlow 1.0 Features Reply message.
class Reply
class Reply < OpenFlow::Message
# Message body of features reply.
class Body < BinData::Record
extend OpenFlow::Flags
Expand Down Expand Up @@ -115,14 +101,6 @@ def physical_ports
end
end

def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
raise Pio::ParseError, 'Invalid Features Reply message.'
end

# rubocop:disable MethodLength
def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
Expand All @@ -138,10 +116,6 @@ def initialize(user_options = {})
@format = Format.new(header: header_options, body: body_options)
end
# rubocop:enable MethodLength

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end
end
end
38 changes: 24 additions & 14 deletions lib/pio/open_flow10/flow_mod.rb
@@ -1,12 +1,11 @@
require 'pio/open_flow'
require 'pio/open_flow10/actions'
require 'pio/open_flow10/match'
require 'pio/open_flow10/message'

# Base module.
module Pio
# OpenFlow 1.0 Flow Mod message.
class FlowMod
class FlowMod < OpenFlow::Message
# enum ofp_flow_mod_command
class Command < BinData::Primitive
COMMANDS = {
Expand Down Expand Up @@ -74,18 +73,29 @@ def length
64 + actions.binary.length
end
end
end

OpenFlow::Message.factory(FlowMod, OpenFlow::FLOW_MOD) do
def_delegators :body, :match
def_delegators :body, :cookie
def_delegators :body, :command
def_delegators :body, :idle_timeout
def_delegators :body, :hard_timeout
def_delegators :body, :priority
def_delegators :body, :buffer_id
def_delegators :body, :out_port
def_delegators :body, :flags
def_delegators :body, :actions
# OpenFlow 1.0 Flow Mod message format.
class Format < BinData::Record
extend OpenFlow::Format

header version: 1, message_type: OpenFlow::FLOW_MOD
body :body
end

# rubocop:disable MethodLength
def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = if user_options.respond_to?(:fetch)
user_options.delete :transaction_id
user_options.delete :xid
dpid = user_options[:dpid]
user_options[:datapath_id] = dpid if dpid
user_options
else
''
end
@format = Format.new(header: header_options, body: body_options)
end
# rubocop:enable MethodLength
end
end
14 changes: 1 addition & 13 deletions lib/pio/open_flow10/hello.rb
Expand Up @@ -3,7 +3,7 @@
# Base module.
module Pio
# OpenFlow 1.0 Hello message
class Hello
class Hello < OpenFlow::Message
# OpenFlow 1.0 Hello message
class Format < BinData::Record
extend OpenFlow::Format
Expand All @@ -12,22 +12,10 @@ class Format < BinData::Record
string :body
end

def self.read(raw_data)
allocate.tap do |message|
message.instance_variable_set(:@format, Format.read(raw_data))
end
rescue BinData::ValidityError
raise Pio::ParseError, 'Invalid Hello message.'
end

def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = user_options[:body] || user_options[:user_data] || ''
@format = Format.new(header: header_options, body: body_options)
end

def method_missing(method, *args, &block)
@format.__send__ method, *args, &block
end
end
end
59 changes: 0 additions & 59 deletions lib/pio/open_flow10/message.rb

This file was deleted.

29 changes: 25 additions & 4 deletions lib/pio/open_flow10/packet_in.rb
@@ -1,4 +1,3 @@
require 'bindata'
require 'pio/ethernet_header'
require 'pio/ipv4_header'
require 'pio/open_flow'
Expand All @@ -8,7 +7,7 @@
# Base module.
module Pio
# OpenFlow 1.0 Packet-In message
class PacketIn
class PacketIn < OpenFlow::Message
# Why is this packet being sent to the controller?
# (enum ofp_packet_in_reason)
class Reason < BinData::Primitive
Expand Down Expand Up @@ -57,11 +56,33 @@ def method_missing(method, *args)
data.__send__(method, *args).snapshot
end
end
end

OpenFlow::Message.factory(PacketIn, OpenFlow::PACKET_IN) do
attr_accessor :datapath_id
alias_method :dpid, :datapath_id
alias_method :dpid=, :datapath_id=

# OpenFlow 1.0 Flow Mod message format.
class Format < BinData::Record
extend OpenFlow::Format

header version: 1, message_type: OpenFlow::PACKET_IN
body :body
end

# rubocop:disable MethodLength
def initialize(user_options = {})
header_options = OpenFlowHeader::Options.parse(user_options)
body_options = if user_options.respond_to?(:fetch)
user_options.delete :transaction_id
user_options.delete :xid
dpid = user_options[:dpid]
user_options[:datapath_id] = dpid if dpid
user_options
else
''
end
@format = Format.new(header: header_options, body: body_options)
end
# rubocop:enable MethodLength
end
end

0 comments on commit 87793a1

Please sign in to comment.