blob: 637ab3eac5a23330681560d379a2e1190c0db229 [file] [log] [blame]
Pavlin Radoslavovcdda1f72013-05-07 23:19:38 +00001#! /usr/bin/env python
2# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
3
4import copy
5import pprint
6import os
7import sys
8import subprocess
9import json
10import argparse
11import io
12import time
13
14from flask import Flask, json, Response, render_template, make_response, request
15
16## Global Var ##
17ControllerIP = "127.0.0.1"
18ControllerPort = 8080
19ReadFromFile = ""
20
21DEBUG=0
22pp = pprint.PrettyPrinter(indent=4)
23
24app = Flask(__name__)
25
26## Worker Functions ##
27def log_error(txt):
28 print '%s' % (txt)
29
30def debug(txt):
31 if DEBUG:
32 print '%s' % (txt)
33
34def measurement_store_path_flow(flow_path):
35 flow_path_json = json.dumps(flow_path)
36
37 try:
38 command = "curl -s -H 'Content-Type: application/json' -d '%s' http://%s:%s/wm/flow/measurement-store-path/json" % (flow_path_json, ControllerIP, ControllerPort)
39 debug("measurement_store_path_flow %s" % command)
40 result = os.popen(command).read()
41 debug("result %s" % result)
42 # parsedResult = json.loads(result)
43 # debug("parsed %s" % parsedResult)
44 except:
45 log_error("Controller IF has issue")
46 exit(1)
47
48def extract_flow_args(my_args):
49 # Check the arguments
50 if len(my_args) < 6:
51 log_error(usage_msg)
52 exit(1)
53
54 # Extract the mandatory arguments
55 my_flow_id = my_args[0]
56 my_installer_id = my_args[1]
57 my_src_dpid = my_args[2]
58 my_src_port = my_args[3]
59 my_dst_dpid = my_args[4]
60 my_dst_port = my_args[5]
61
62 #
63 # Extract the "match" and "action" arguments
64 #
65 match = {}
66 matchInPortEnabled = True # NOTE: Enabled by default
67 actions = []
68 actionOutputEnabled = True # NOTE: Enabled by default
69 idx = 6
70 while idx < len(my_args):
71 action = {}
72 arg1 = my_args[idx]
73 idx = idx + 1
74 # Extract the second argument
75 if idx >= len(my_args):
76 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
77 log_error(error_arg)
78 log_error(usage_msg)
79 exit(1)
80 arg2 = my_args[idx]
81 idx = idx + 1
82
83 if arg1 == "matchInPort":
84 # Just mark whether inPort matching is enabled
85 matchInPortEnabled = arg2 in ['True', 'true']
86 # inPort = {}
87 # inPort['value'] = int(arg2, 0)
88 # match['inPort'] = inPort
89 ## match['matchInPort'] = True
90 elif arg1 == "matchSrcMac":
91 srcMac = {}
92 srcMac['value'] = arg2
93 match['srcMac'] = srcMac
94 # match['matchSrcMac'] = True
95 elif arg1 == "matchDstMac":
96 dstMac = {}
97 dstMac['value'] = arg2
98 match['dstMac'] = dstMac
99 # match['matchDstMac'] = True
100 elif arg1 == "matchVlanId":
101 match['vlanId'] = int(arg2, 0)
102 # match['matchVlanId'] = True
103 elif arg1 == "matchVlanPriority":
104 match['vlanPriority'] = int(arg2, 0)
105 # match['matchVlanPriority'] = True
106 elif arg1 == "matchEthernetFrameType":
107 match['ethernetFrameType'] = int(arg2, 0)
108 # match['matchEthernetFrameType'] = True
109 elif arg1 == "matchIpToS":
110 match['ipToS'] = int(arg2, 0)
111 # match['matchIpToS'] = True
112 elif arg1 == "matchIpProto":
113 match['ipProto'] = int(arg2, 0)
114 # match['matchIpProto'] = True
115 elif arg1 == "matchSrcIPv4Net":
116 srcIPv4Net = {}
117 srcIPv4Net['value'] = arg2
118 match['srcIPv4Net'] = srcIPv4Net
119 # match['matchSrcIPv4Net'] = True
120 elif arg1 == "matchDstIPv4Net":
121 dstIPv4Net = {}
122 dstIPv4Net['value'] = arg2
123 match['dstIPv4Net'] = dstIPv4Net
124 # match['matchDstIPv4Net'] = True
125 elif arg1 == "matchSrcTcpUdpPort":
126 match['srcTcpUdpPort'] = int(arg2, 0)
127 # match['matchSrcTcpUdpPort'] = True
128 elif arg1 == "matchDstTcpUdpPort":
129 match['dstTcpUdpPort'] = int(arg2, 0)
130 # match['matchDstTcpUdpPort'] = True
131 elif arg1 == "actionOutput":
132 # Just mark whether ACTION_OUTPUT action is enabled
133 actionOutputEnabled = arg2 in ['True', 'true']
134 #
135 # TODO: Complete the implementation for ACTION_OUTPUT
136 # actionOutput = {}
137 # outPort = {}
138 # outPort['value'] = int(arg2, 0)
139 # actionOutput['port'] = outPort
140 # actionOutput['maxLen'] = int(arg3, 0)
141 # action['actionOutput'] = actionOutput
142 # # action['actionType'] = 'ACTION_OUTPUT'
143 # actions.append(action)
144 #
145 elif arg1 == "actionSetVlanId":
146 vlanId = {}
147 vlanId['vlanId'] = int(arg2, 0)
148 action['actionSetVlanId'] = vlanId
149 # action['actionType'] = 'ACTION_SET_VLAN_VID'
150 actions.append(copy.deepcopy(action))
151 elif arg1 == "actionSetVlanPriority":
152 vlanPriority = {}
153 vlanPriority['vlanPriority'] = int(arg2, 0)
154 action['actionSetVlanPriority'] = vlanPriority
155 # action['actionType'] = 'ACTION_SET_VLAN_PCP'
156 actions.append(copy.deepcopy(action))
157 elif arg1 == "actionSetIpToS":
158 ipToS = {}
159 ipToS['ipToS'] = int(arg2, 0)
160 action['actionSetIpToS'] = ipToS
161 # action['actionType'] = 'ACTION_SET_NW_TOS'
162 actions.append(copy.deepcopy(action))
163 elif arg1 == "actionSetTcpUdpSrcPort":
164 tcpUdpSrcPort = {}
165 tcpUdpSrcPort['port'] = int(arg2, 0)
166 action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
167 # action['actionType'] = 'ACTION_SET_TP_SRC'
168 actions.append(copy.deepcopy(action))
169 elif arg1 == "actionSetTcpUdpDstPort":
170 tcpUdpDstPort = {}
171 tcpUdpDstPort['port'] = int(arg2, 0)
172 action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
173 # action['actionType'] = 'ACTION_SET_TP_DST'
174 actions.append(copy.deepcopy(action))
175 elif arg1 == "actionStripVlan":
176 stripVlan = {}
177 stripVlan['stripVlan'] = arg2 in ['True', 'true']
178 action['actionStripVlan'] = stripVlan
179 # action['actionType'] = 'ACTION_STRIP_VLAN'
180 actions.append(copy.deepcopy(action))
181 elif arg1 == "actionSetEthernetSrcAddr":
182 ethernetSrcAddr = {}
183 ethernetSrcAddr['value'] = arg2
184 setEthernetSrcAddr = {}
185 setEthernetSrcAddr['addr'] = ethernetSrcAddr
186 action['actionSetEthernetSrcAddr'] = setEthernetSrcAddr
187 # action['actionType'] = 'ACTION_SET_DL_SRC'
188 actions.append(copy.deepcopy(action))
189 elif arg1 == "actionSetEthernetDstAddr":
190 ethernetDstAddr = {}
191 ethernetDstAddr['value'] = arg2
192 setEthernetDstAddr = {}
193 setEthernetDstAddr['addr'] = ethernetDstAddr
194 action['actionSetEthernetDstAddr'] = setEthernetDstAddr
195 # action['actionType'] = 'ACTION_SET_DL_DST'
196 actions.append(copy.deepcopy(action))
197 elif arg1 == "actionSetIPv4SrcAddr":
198 IPv4SrcAddr = {}
199 IPv4SrcAddr['value'] = arg2
200 setIPv4SrcAddr = {}
201 setIPv4SrcAddr['addr'] = IPv4SrcAddr
202 action['actionSetIPv4SrcAddr'] = setIPv4SrcAddr
203 # action['actionType'] = 'ACTION_SET_NW_SRC'
204 actions.append(copy.deepcopy(action))
205 elif arg1 == "actionSetIPv4DstAddr":
206 IPv4DstAddr = {}
207 IPv4DstAddr['value'] = arg2
208 setIPv4DstAddr = {}
209 setIPv4DstAddr['addr'] = IPv4DstAddr
210 action['actionSetIPv4DstAddr'] = setIPv4DstAddr
211 # action['actionType'] = 'ACTION_SET_NW_DST'
212 actions.append(copy.deepcopy(action))
213 elif arg1 == "actionEnqueue":
214 # TODO: Implement ACTION_ENQUEUE
215 actionEnqueue = {}
216 # actionEnqueue['queueId'] = int(arg2, 0)
217 # enqueuePort = {}
218 # enqueuePort['value'] = int(arg3, 0)
219 # actionEnqueue['port'] = enqueuePort
220 # action['actionEnqueue'] = actionEnqueue
221 # # action['actionType'] = 'ACTION_ENQUEUE'
222 # actions.append(copy.deepcopy(action))
223 #
224 else:
225 log_error("ERROR: Unknown argument '%s'" % (arg1))
226 log_error(usage_msg)
227 exit(1)
228
229 return {
230 'my_flow_id' : my_flow_id,
231 'my_installer_id' : my_installer_id,
232 'my_src_dpid' : my_src_dpid,
233 'my_src_port' : my_src_port,
234 'my_dst_dpid' : my_dst_dpid,
235 'my_dst_port' : my_dst_port,
236 'match' : match,
237 'matchInPortEnabled' : matchInPortEnabled,
238 'actions' : actions,
239 'actionOutputEnabled' : actionOutputEnabled
240 }
241
242def compute_flow_path(parsed_args, data_path):
243
244 my_flow_id = parsed_args['my_flow_id']
245 my_installer_id = parsed_args['my_installer_id']
246 match = parsed_args['match']
247 matchInPortEnabled = parsed_args['matchInPortEnabled']
248 actions = parsed_args['actions']
249 actionOutputEnabled = parsed_args['actionOutputEnabled']
250 my_data_path = copy.deepcopy(data_path)
251
252 flow_id = {}
253 flow_id['value'] = my_flow_id
254 installer_id = {}
255 installer_id['value'] = my_installer_id
256
257 flow_path = {}
258 flow_path['flowId'] = flow_id
259 flow_path['installerId'] = installer_id
260
261 if (len(match) > 0):
262 flow_path['flowEntryMatch'] = copy.deepcopy(match)
263
264 #
265 # Add the match conditions to each flow entry
266 #
267 if (len(match) > 0) or matchInPortEnabled:
268 idx = 0
269 while idx < len(my_data_path['flowEntries']):
270 if matchInPortEnabled:
271 inPort = my_data_path['flowEntries'][idx]['inPort']
272 match['inPort'] = copy.deepcopy(inPort)
273 # match['matchInPort'] = True
274 my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
275 idx = idx + 1
276
277 #
278 # Set the actions for each flow entry
279 # NOTE: The actions from the command line are aplied
280 # ONLY to the first flow entry.
281 #
282 # If ACTION_OUTPUT action is enabled, then apply it
283 # to each flow entry.
284 #
285 if (len(actions) > 0) or actionOutputEnabled:
286 idx = 0
287 while idx < len(my_data_path['flowEntries']):
288 if idx > 0:
289 actions = [] # Reset the actions for all but first entry
290 action = {}
291 outPort = my_data_path['flowEntries'][idx]['outPort']
292 actionOutput = {}
293 actionOutput['port'] = copy.deepcopy(outPort)
294 # actionOutput['maxLen'] = 0 # TODO: not used for now
295 action['actionOutput'] = copy.deepcopy(actionOutput)
296 # action['actionType'] = 'ACTION_OUTPUT'
297 actions.append(copy.deepcopy(action))
298
299 my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
300 idx = idx + 1
301
302
303 flow_path['dataPath'] = my_data_path
304 debug("Flow Path: %s" % flow_path)
305 return flow_path
306
307def measurement_store_paths(parsed_args):
308 idx = 0
309 while idx < len(parsed_args):
310 data_path = {}
311 src_dpid = {}
312 src_port = {}
313 dst_dpid = {}
314 dst_port = {}
315 src_switch_port = {}
316 dst_switch_port = {}
317 flow_entries = []
318
319 src_dpid['value'] = parsed_args[idx]['my_src_dpid']
320 src_port['value'] = parsed_args[idx]['my_src_port']
321 dst_dpid['value'] = parsed_args[idx]['my_dst_dpid']
322 dst_port['value'] = parsed_args[idx]['my_dst_port']
323 src_switch_port['dpid'] = src_dpid
324 src_switch_port['port'] = src_port
325 dst_switch_port['dpid'] = dst_dpid
326 dst_switch_port['port'] = dst_port
327
328 data_path['srcPort'] = copy.deepcopy(src_switch_port)
329 data_path['dstPort'] = copy.deepcopy(dst_switch_port)
330 data_path['flowEntries'] = copy.deepcopy(flow_entries)
331
332 #
333 # XXX: Explicitly disable the InPort matching, and
334 # the Output action, because they get in the way
335 # during the compute_flow_path() processing.
336 #
337 parsed_args[idx]['matchInPortEnabled'] = False
338 parsed_args[idx]['actionOutputEnabled'] = False
339
340 flow_path = compute_flow_path(parsed_args[idx], data_path)
341 measurement_store_path_flow(flow_path)
342
343 idx = idx + 1
344
345
346if __name__ == "__main__":
347 usage_msg = "Store Flow Paths into ONOS for measurement purpose.\n"
348 usage_msg = usage_msg + "\n"
349 usage_msg = usage_msg + "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Match Conditions] [Actions]\n" % (sys.argv[0])
350 usage_msg = usage_msg + "\n"
351 usage_msg = usage_msg + " Flags:\n"
352 usage_msg = usage_msg + " -f <filename> Read the flow(s) to install from a file\n"
353 usage_msg = usage_msg + " File format: one line per flow starting with <flow-id>\n"
354 usage_msg = usage_msg + "\n"
355 usage_msg = usage_msg + " Match Conditions:\n"
356 usage_msg = usage_msg + " matchInPort <True|False> (default to True)\n"
357 usage_msg = usage_msg + " matchSrcMac <source MAC address>\n"
358 usage_msg = usage_msg + " matchDstMac <destination MAC address>\n"
359 usage_msg = usage_msg + " matchSrcIPv4Net <source IPv4 network address>\n"
360 usage_msg = usage_msg + " matchDstIPv4Net <destination IPv4 network address>\n"
361 usage_msg = usage_msg + " matchEthernetFrameType <Ethernet frame type>\n"
362 usage_msg = usage_msg + "\n"
363 usage_msg = usage_msg + " Match Conditions (not implemented yet):\n"
364 usage_msg = usage_msg + " matchVlanId <VLAN ID>\n"
365 usage_msg = usage_msg + " matchVlanPriority <VLAN priority>\n"
366 usage_msg = usage_msg + " matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
367 usage_msg = usage_msg + " matchIpProto <IP protocol>\n"
368 usage_msg = usage_msg + " matchSrcTcpUdpPort <source TCP/UDP port>\n"
369 usage_msg = usage_msg + " matchDstTcpUdpPort <destination TCP/UDP port>\n"
370 usage_msg = usage_msg + "\n"
371 usage_msg = usage_msg + " Actions:\n"
372 usage_msg = usage_msg + " actionOutput <True|False> (default to True)\n"
373 usage_msg = usage_msg + " actionSetEthernetSrcAddr <source MAC address>\n"
374 usage_msg = usage_msg + " actionSetEthernetDstAddr <destination MAC address>\n"
375 usage_msg = usage_msg + " actionSetIPv4SrcAddr <source IPv4 address>\n"
376 usage_msg = usage_msg + " actionSetIPv4DstAddr <destination IPv4 address>\n"
377 usage_msg = usage_msg + "\n"
378 usage_msg = usage_msg + " Actions (not implemented yet):\n"
379 usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
380 usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
381 usage_msg = usage_msg + " actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
382 usage_msg = usage_msg + " actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
383 usage_msg = usage_msg + " actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
384 usage_msg = usage_msg + " actionStripVlan <True|False>\n"
385 usage_msg = usage_msg + " actionEnqueue <dummy argument>\n"
386
387 # app.debug = False;
388
389 # Usage info
390 if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
391 print(usage_msg)
392 exit(0)
393
394 #
395 # Check the flags
396 #
397 start_argv_index = 1
398 idx = 1
399 while idx < len(sys.argv):
400 arg1 = sys.argv[idx]
401 idx = idx + 1
402 if arg1 == "-f":
403 if idx >= len(sys.argv):
404 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
405 log_error(error_arg)
406 log_error(usage_msg)
407 exit(1)
408 ReadFromFile = sys.argv[idx]
409 idx = idx + 1
410 start_argv_index = idx
411 else:
412 break;
413
414 #
415 # Read the arguments from a file or from the remaining command line options
416 #
417 my_lines = []
418 if len(ReadFromFile) > 0:
419 f = open(ReadFromFile, "rt")
420 my_line = f.readline()
421 while my_line:
422 if len(my_line.rstrip()) > 0 and my_line[0] != "#":
423 my_token_line = my_line.rstrip().split()
424 my_lines.append(my_token_line)
425 my_line = f.readline()
426 else:
427 my_lines.append(copy.deepcopy(sys.argv[start_argv_index:]))
428
429 #
430 # Initialization
431 #
432 last_data_paths = []
433 parsed_args = []
434 idx = 0
435 while idx < len(my_lines):
436 last_data_path = []
437 last_data_paths.append(copy.deepcopy(last_data_path))
438 #
439 # Parse the flow arguments
440 #
441 my_args = my_lines[idx]
442 parsed_args.append(copy.deepcopy(extract_flow_args(my_args)))
443
444 idx = idx + 1
445
446 #
447 measurement_store_paths(parsed_args)