1
|
|
|
"""Helper python-openflow functions.""" |
2
|
|
|
|
3
|
|
|
# System imports |
4
|
|
|
|
5
|
|
|
# Third-party imports |
6
|
|
|
|
7
|
|
|
# Local source tree imports |
8
|
|
|
# Importing asynchronous messages |
9
|
1 |
|
from pyof.v0x04.asynchronous.error_msg import ErrorMsg |
10
|
1 |
|
from pyof.v0x04.asynchronous.flow_removed import FlowRemoved |
11
|
1 |
|
from pyof.v0x04.asynchronous.packet_in import PacketIn |
12
|
1 |
|
from pyof.v0x04.asynchronous.port_status import PortStatus |
13
|
|
|
# Importing controller2switch messages |
14
|
1 |
|
from pyof.v0x04.common.header import Header, Type |
15
|
1 |
|
from pyof.v0x04.controller2switch.barrier_reply import BarrierReply |
16
|
1 |
|
from pyof.v0x04.controller2switch.barrier_request import BarrierRequest |
17
|
1 |
|
from pyof.v0x04.controller2switch.features_reply import FeaturesReply |
18
|
1 |
|
from pyof.v0x04.controller2switch.features_request import FeaturesRequest |
19
|
1 |
|
from pyof.v0x04.controller2switch.flow_mod import FlowMod |
20
|
1 |
|
from pyof.v0x04.controller2switch.get_async_reply import GetAsyncReply |
21
|
1 |
|
from pyof.v0x04.controller2switch.get_async_request import GetAsyncRequest |
22
|
1 |
|
from pyof.v0x04.controller2switch.get_config_reply import GetConfigReply |
23
|
1 |
|
from pyof.v0x04.controller2switch.get_config_request import GetConfigRequest |
24
|
1 |
|
from pyof.v0x04.controller2switch.group_mod import GroupMod |
25
|
1 |
|
from pyof.v0x04.controller2switch.meter_mod import MeterMod |
26
|
1 |
|
from pyof.v0x04.controller2switch.multipart_reply import MultipartReply |
27
|
1 |
|
from pyof.v0x04.controller2switch.multipart_request import MultipartRequest |
28
|
1 |
|
from pyof.v0x04.controller2switch.packet_out import PacketOut |
29
|
1 |
|
from pyof.v0x04.controller2switch.port_mod import PortMod |
30
|
1 |
|
from pyof.v0x04.controller2switch.queue_get_config_reply import ( |
31
|
|
|
QueueGetConfigReply) |
32
|
1 |
|
from pyof.v0x04.controller2switch.queue_get_config_request import ( |
33
|
|
|
QueueGetConfigRequest) |
34
|
1 |
|
from pyof.v0x04.controller2switch.role_reply import RoleReply |
35
|
1 |
|
from pyof.v0x04.controller2switch.role_request import RoleRequest |
36
|
1 |
|
from pyof.v0x04.controller2switch.set_async import SetAsync |
37
|
1 |
|
from pyof.v0x04.controller2switch.set_config import SetConfig |
38
|
1 |
|
from pyof.v0x04.controller2switch.table_mod import TableMod |
39
|
|
|
# Importing symmetric messages |
40
|
1 |
|
from pyof.v0x04.symmetric.echo_reply import EchoReply |
41
|
1 |
|
from pyof.v0x04.symmetric.echo_request import EchoRequest |
42
|
1 |
|
from pyof.v0x04.symmetric.experimenter import ExperimenterHeader |
43
|
1 |
|
from pyof.v0x04.symmetric.hello import Hello |
44
|
|
|
|
45
|
1 |
|
__all__ = ('MESSAGE_TYPES', 'new_message_from_header', |
46
|
|
|
'new_message_from_message_type', 'unpack_message') |
47
|
|
|
|
48
|
1 |
|
MESSAGE_TYPES = { |
49
|
|
|
|
50
|
|
|
# Symetric/Immutable messages |
51
|
|
|
str(Type.OFPT_HELLO): Hello, |
52
|
|
|
str(Type.OFPT_ERROR): ErrorMsg, |
53
|
|
|
str(Type.OFPT_ECHO_REQUEST): EchoRequest, |
54
|
|
|
str(Type.OFPT_ECHO_REPLY): EchoReply, |
55
|
|
|
str(Type.OFPT_EXPERIMENTER): ExperimenterHeader, |
56
|
|
|
|
57
|
|
|
# Switch configuration messages |
58
|
|
|
# Controller/Switch messages |
59
|
|
|
str(Type.OFPT_FEATURES_REQUEST): FeaturesRequest, |
60
|
|
|
str(Type.OFPT_FEATURES_REPLY): FeaturesReply, |
61
|
|
|
str(Type.OFPT_GET_CONFIG_REQUEST): GetConfigRequest, |
62
|
|
|
str(Type.OFPT_GET_CONFIG_REPLY): GetConfigReply, |
63
|
|
|
str(Type.OFPT_SET_CONFIG): SetConfig, |
64
|
|
|
|
65
|
|
|
# Async messages |
66
|
|
|
str(Type.OFPT_PACKET_IN): PacketIn, |
67
|
|
|
str(Type.OFPT_FLOW_REMOVED): FlowRemoved, |
68
|
|
|
str(Type.OFPT_PORT_STATUS): PortStatus, |
69
|
|
|
|
70
|
|
|
# Controller command messages |
71
|
|
|
# Controller/Switch message |
72
|
|
|
str(Type.OFPT_PACKET_OUT): PacketOut, |
73
|
|
|
str(Type.OFPT_FLOW_MOD): FlowMod, |
74
|
|
|
str(Type.OFPT_GROUP_MOD): GroupMod, |
75
|
|
|
str(Type.OFPT_PORT_MOD): PortMod, |
76
|
|
|
str(Type.OFPT_TABLE_MOD): TableMod, |
77
|
|
|
|
78
|
|
|
# Multipart messages. |
79
|
|
|
# Controller/Switch message |
80
|
|
|
str(Type.OFPT_MULTIPART_REPLY): MultipartReply, |
81
|
|
|
str(Type.OFPT_MULTIPART_REQUEST): MultipartRequest, |
82
|
|
|
|
83
|
|
|
# Barrier messages |
84
|
|
|
# Controller/Switch message |
85
|
|
|
str(Type.OFPT_BARRIER_REQUEST): BarrierRequest, |
86
|
|
|
str(Type.OFPT_BARRIER_REPLY): BarrierReply, |
87
|
|
|
|
88
|
|
|
# Queue Configuration messages |
89
|
|
|
# Controller/Switch message |
90
|
|
|
str(Type.OFPT_QUEUE_GET_CONFIG_REQUEST): QueueGetConfigRequest, |
91
|
|
|
str(Type.OFPT_QUEUE_GET_CONFIG_REPLY): QueueGetConfigReply, |
92
|
|
|
|
93
|
|
|
# Controller role change request message |
94
|
|
|
# Controller/Switch message |
95
|
|
|
str(Type.OFPT_ROLE_REQUEST): RoleRequest, |
96
|
|
|
str(Type.OFPT_ROLE_REPLY): RoleReply, |
97
|
|
|
|
98
|
|
|
# Asynchronous message configuration |
99
|
|
|
# Controller/Switch message |
100
|
|
|
str(Type.OFPT_GET_ASYNC_REQUEST): GetAsyncRequest, |
101
|
|
|
str(Type.OFPT_GET_ASYNC_REPLY): GetAsyncReply, |
102
|
|
|
str(Type.OFPT_SET_ASYNC): SetAsync, |
103
|
|
|
|
104
|
|
|
# Meters and rate limiters configuration messages |
105
|
|
|
# Controller/Switch message |
106
|
|
|
str(Type.OFPT_METER_MOD): MeterMod, |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
|
110
|
1 |
|
def new_message_from_message_type(message_type): |
111
|
|
|
"""Given an OpenFlow Message Type, return an empty message of that type. |
112
|
|
|
|
113
|
|
|
Args: |
114
|
|
|
messageType (:class:`~pyof.v0x04.common.header.Type`): |
115
|
|
|
Python-openflow message. |
116
|
|
|
|
117
|
|
|
Returns: |
118
|
|
|
Empty OpenFlow message of the requested message type. |
119
|
|
|
|
120
|
|
|
Raises: |
121
|
|
|
KytosUndefinedMessageType: Unkown Message_Type. |
122
|
|
|
|
123
|
|
|
""" |
124
|
1 |
|
message_type = str(message_type) |
125
|
1 |
|
if message_type not in MESSAGE_TYPES: |
126
|
|
|
msg = "Define class for {} in {}".format(message_type, __file__) |
127
|
|
|
raise ValueError(msg) |
128
|
|
|
|
129
|
1 |
|
message_class = MESSAGE_TYPES.get(message_type) |
130
|
1 |
|
message_instance = message_class() |
131
|
|
|
|
132
|
1 |
|
return message_instance |
133
|
|
|
|
134
|
|
|
|
135
|
1 |
View Code Duplication |
def new_message_from_header(header): |
|
|
|
|
136
|
|
|
"""Given an OF Header, return an empty message of header's message_type. |
137
|
|
|
|
138
|
|
|
Args: |
139
|
|
|
header (:class:`~pyof.v0x04.common.header.Header`): |
140
|
|
|
Unpacked OpenFlow Header. |
141
|
|
|
|
142
|
|
|
Returns: |
143
|
|
|
Empty OpenFlow message of the same type of message_type attribute from |
144
|
|
|
the given header. |
145
|
|
|
The header attribute of the message will be populated. |
146
|
|
|
|
147
|
|
|
Raises: |
148
|
|
|
KytosUndefinedMessageType: Unkown Message_Type. |
149
|
|
|
|
150
|
|
|
""" |
151
|
1 |
|
message_type = header.message_type |
152
|
1 |
|
if not isinstance(message_type, Type): |
153
|
1 |
|
try: |
154
|
1 |
|
if isinstance(message_type, str): |
155
|
|
|
message_type = Type[message_type] |
156
|
1 |
|
elif isinstance(message_type, int): |
157
|
|
|
message_type = Type(message_type) |
158
|
|
|
except ValueError: |
159
|
|
|
raise ValueError |
160
|
|
|
|
161
|
1 |
|
message = new_message_from_message_type(message_type) |
162
|
1 |
|
message.header.xid = header.xid |
163
|
1 |
|
message.header.length = header.length |
164
|
|
|
|
165
|
1 |
|
return message |
166
|
|
|
|
167
|
|
|
|
168
|
1 |
View Code Duplication |
def unpack_message(buffer): |
|
|
|
|
169
|
|
|
"""Unpack the whole buffer, including header pack. |
170
|
|
|
|
171
|
|
|
Args: |
172
|
|
|
buffer (bytes): Bytes representation of a openflow message. |
173
|
|
|
|
174
|
|
|
Returns: |
175
|
|
|
object: Instance of openflow message. |
176
|
|
|
|
177
|
|
|
""" |
178
|
1 |
|
hdr_size = Header().get_size() |
179
|
1 |
|
hdr_buff, msg_buff = buffer[:hdr_size], buffer[hdr_size:] |
180
|
1 |
|
header = Header() |
181
|
1 |
|
header.unpack(hdr_buff) |
182
|
1 |
|
message = new_message_from_header(header) |
183
|
1 |
|
message.unpack(msg_buff) |
184
|
|
|
return message |
185
|
|
|
|