blob: 30669367d7068a4a65e449664f48d00a6c158974 [file] [log] [blame]
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -08001#! /usr/bin/env python
2# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
3
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -07004import copy
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -08005import 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#
Naoki Shiota862cc3b2013-12-13 15:42:50 -080017# curl http://127.0.0.1:8080/wm/onos/topology/route/00:00:00:00:00:00:0a:01/1/00:00:00:00:00:00:0a:04/1/json
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080018#
19
20## Global Var ##
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070021ControllerIP = "127.0.0.1"
22ControllerPort = 8080
23MonitoringEnabled = False
Pavlin Radoslavovb549f082013-03-29 04:28:27 -070024MonitoringByOnos = False
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070025ReadFromFile = ""
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080026
27DEBUG=0
28pp = pprint.PrettyPrinter(indent=4)
29
30app = Flask(__name__)
31
32## Worker Functions ##
33def log_error(txt):
34 print '%s' % (txt)
35
36def debug(txt):
37 if DEBUG:
38 print '%s' % (txt)
39
Naoki Shiota862cc3b2013-12-13 15:42:50 -080040# @app.route("/wm/onos/topology/route/<srcdpid>/<srcport>/<destdpid>/<destport>/json")
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080041#
42# Sample output:
43# {'dstPort': {'port': {'value': 0}, 'dpid': {'value': '00:00:00:00:00:00:00:02'}}, 'srcPort': {'port': {'value': 0}, 'dpid': {'value': '00:00:00:00:00:00:00:01'}}, 'flowEntries': [{'outPort': {'value': 1}, 'flowEntryErrorState': None, 'flowEntryMatch': None, 'flowEntryActions': None, 'inPort': {'value': 0}, 'flowEntryId': None, 'flowEntryUserState': 'FE_USER_UNKNOWN', 'dpid': {'value': '00:00:00:00:00:00:00:01'}, 'flowEntrySwitchState': 'FE_SWITCH_UNKNOWN'}, {'outPort': {'value': 0}, 'flowEntryErrorState': None, 'flowEntryMatch': None, 'flowEntryActions': None, 'inPort': {'value': 9}, 'flowEntryId': None, 'flowEntryUserState': 'FE_USER_UNKNOWN', 'dpid': {'value': '00:00:00:00:00:00:00:02'}, 'flowEntrySwitchState': 'FE_SWITCH_UNKNOWN'}]}
44#
45def shortest_path(v1, p1, v2, p2):
46 try:
Naoki Shiota862cc3b2013-12-13 15:42:50 -080047 command = "curl -s http://%s:%s/wm/onos/topology/route/%s/%s/%s/%s/json" % (ControllerIP, ControllerPort, v1, p1, v2, p2)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080048 debug("shortest_path %s" % command)
Pavlin Radoslavoveb2d5a22013-03-14 19:58:14 -070049 parsedResult = []
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080050
51 result = os.popen(command).read()
52 debug("result %s" % result)
53 if len(result) == 0:
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070054 log_error("No Path found from %s/%s to %s/%s" % (v1, p1, v2, p2))
55 else:
56 parsedResult = json.loads(result)
57 debug("parsed %s" % parsedResult)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080058
59 except:
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070060 log_error("Controller IF has issue: No Path found from %s/%s to %s/%s" % (v1, p1, v2, p2))
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080061
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070062 return parsedResult
63
64def print_data_path(data_path):
65 if len(data_path) == 0:
66 return
67
68 srcSwitch = data_path['srcPort']['dpid']['value'];
69 srcPort = data_path['srcPort']['port']['value'];
70 dstSwitch = data_path['dstPort']['dpid']['value'];
71 dstPort = data_path['dstPort']['port']['value'];
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080072
73 print "DataPath: (src = %s/%s dst = %s/%s)" % (srcSwitch, srcPort, dstSwitch, dstPort);
74
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070075 for f in data_path['flowEntries']:
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080076 inPort = f['inPort']['value'];
77 outPort = f['outPort']['value'];
78 dpid = f['dpid']['value']
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070079 print " FlowEntry: (%s, %s, %s)" % (inPort, dpid, outPort)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080080
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080081def add_flow_path(flow_path):
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070082 flow_path_json = json.dumps(flow_path)
83
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080084 try:
Naoki Shiota862cc3b2013-12-13 15:42:50 -080085 command = "curl -s -H 'Content-Type: application/json' -d '%s' http://%s:%s/wm/onos/flows/add/json" % (flow_path_json, ControllerIP, ControllerPort)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080086 debug("add_flow_path %s" % command)
87 result = os.popen(command).read()
88 debug("result %s" % result)
89 # parsedResult = json.loads(result)
90 # debug("parsed %s" % parsedResult)
91 except:
92 log_error("Controller IF has issue")
93 exit(1)
94
Pavlin Radoslavovb549f082013-03-29 04:28:27 -070095def add_shortest_path_flow(flow_path):
96 flow_path_json = json.dumps(flow_path)
97
98 try:
Pavlin Radoslavov953fb0a2013-12-13 18:55:14 -080099 command = "curl -s -H 'Content-Type: application/json' -d '%s' http://%s:%s/wm/onos/flows/add/json" % (flow_path_json, ControllerIP, ControllerPort)
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700100 debug("add_shortest_path_flow %s" % command)
101 result = os.popen(command).read()
102 debug("result %s" % result)
103 # parsedResult = json.loads(result)
104 # debug("parsed %s" % parsedResult)
105 except:
106 log_error("Controller IF has issue")
107 exit(1)
108
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700109def delete_flow_path(flow_id):
Naoki Shiota862cc3b2013-12-13 15:42:50 -0800110 command = "curl -s \"http://%s:%s/wm/onos/flows/delete/%s/json\"" % (ControllerIP, ControllerPort, flow_id)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700111 debug("delete_flow_path %s" % command)
112 result = os.popen(command).read()
113 debug("result %s" % result)
114 # parsedResult = json.loads(result)
115 # debug("parsed %s" % parsedResult)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700116
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700117def extract_flow_args(my_args):
118 # Check the arguments
119 if len(my_args) < 6:
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800120 log_error(usage_msg)
121 exit(1)
122
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700123 # Extract the mandatory arguments
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700124 my_flow_id = my_args[0]
125 my_installer_id = my_args[1]
126 my_src_dpid = my_args[2]
127 my_src_port = my_args[3]
128 my_dst_dpid = my_args[4]
129 my_dst_port = my_args[5]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700130
131 #
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800132 # Extract the "flowPathFlags", "idleTimeout", "hardTimeout", "priority",
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800133 # "match" and "action" arguments.
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700134 #
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700135 flowPathFlags = 0L
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800136 idleTimeout = 0
137 hardTimeout = 0
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800138 priority = 32768
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700139 match = {}
140 matchInPortEnabled = True # NOTE: Enabled by default
141 actions = []
142 actionOutputEnabled = True # NOTE: Enabled by default
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700143 idx = 6
144 while idx < len(my_args):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700145 action = {}
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700146 arg1 = my_args[idx]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700147 idx = idx + 1
148 # Extract the second argument
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700149 if idx >= len(my_args):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700150 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
151 log_error(error_arg)
152 log_error(usage_msg)
153 exit(1)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700154 arg2 = my_args[idx]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700155 idx = idx + 1
156
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700157 if arg1 == "flowPathFlags":
158 if "DISCARD_FIRST_HOP_ENTRY" in arg2:
159 flowPathFlags = flowPathFlags + 0x1
160 if "KEEP_ONLY_FIRST_HOP_ENTRY" in arg2:
161 flowPathFlags = flowPathFlags + 0x2
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800162 elif arg1 == "idleTimeout":
163 idleTimeout = arg2
164 elif arg1 == "hardTimeout":
165 hardTimeout = arg2
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800166 elif arg1 == "priority":
167 priority = arg2
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700168 elif arg1 == "matchInPort":
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700169 # Just mark whether inPort matching is enabled
170 matchInPortEnabled = arg2 in ['True', 'true']
171 # inPort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700172 # inPort['value'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700173 # match['inPort'] = inPort
174 ## match['matchInPort'] = True
175 elif arg1 == "matchSrcMac":
176 srcMac = {}
177 srcMac['value'] = arg2
178 match['srcMac'] = srcMac
179 # match['matchSrcMac'] = True
180 elif arg1 == "matchDstMac":
181 dstMac = {}
182 dstMac['value'] = arg2
183 match['dstMac'] = dstMac
184 # match['matchDstMac'] = True
Pavlin Radoslavovad3a1e62013-07-09 13:30:16 -0700185 elif arg1 == "matchEthernetFrameType":
186 match['ethernetFrameType'] = int(arg2, 0)
187 # match['matchEthernetFrameType'] = True
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700188 elif arg1 == "matchVlanId":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700189 match['vlanId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700190 # match['matchVlanId'] = True
191 elif arg1 == "matchVlanPriority":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700192 match['vlanPriority'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700193 # match['matchVlanPriority'] = True
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700194 elif arg1 == "matchSrcIPv4Net":
195 srcIPv4Net = {}
196 srcIPv4Net['value'] = arg2
197 match['srcIPv4Net'] = srcIPv4Net
198 # match['matchSrcIPv4Net'] = True
199 elif arg1 == "matchDstIPv4Net":
200 dstIPv4Net = {}
201 dstIPv4Net['value'] = arg2
202 match['dstIPv4Net'] = dstIPv4Net
203 # match['matchDstIPv4Net'] = True
Pavlin Radoslavovad3a1e62013-07-09 13:30:16 -0700204 elif arg1 == "matchIpProto":
205 match['ipProto'] = int(arg2, 0)
206 # match['matchIpProto'] = True
207 elif arg1 == "matchIpToS":
208 match['ipToS'] = int(arg2, 0)
209 # match['matchIpToS'] = True
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700210 elif arg1 == "matchSrcTcpUdpPort":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700211 match['srcTcpUdpPort'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700212 # match['matchSrcTcpUdpPort'] = True
213 elif arg1 == "matchDstTcpUdpPort":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700214 match['dstTcpUdpPort'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700215 # match['matchDstTcpUdpPort'] = True
216 elif arg1 == "actionOutput":
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700217 # Mark whether ACTION_OUTPUT action is enabled
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700218 actionOutputEnabled = arg2 in ['True', 'true']
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700219 # If ACTION_OUTPUT is explicitly enabled, add an entry with a fake
220 # port number. We need this entry to preserve the action ordering.
221 if actionOutputEnabled == True:
222 actionOutput = {}
223 outPort = {}
224 outPort['value'] = 0xffff
225 actionOutput['port'] = outPort
226 actionOutput['maxLen'] = 0
227 action['actionOutput'] = actionOutput
228 # action['actionType'] = 'ACTION_OUTPUT'
229 actions.append(action)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700230 #
231 elif arg1 == "actionSetVlanId":
232 vlanId = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700233 vlanId['vlanId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700234 action['actionSetVlanId'] = vlanId
235 # action['actionType'] = 'ACTION_SET_VLAN_VID'
236 actions.append(copy.deepcopy(action))
237 elif arg1 == "actionSetVlanPriority":
238 vlanPriority = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700239 vlanPriority['vlanPriority'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700240 action['actionSetVlanPriority'] = vlanPriority
241 # action['actionType'] = 'ACTION_SET_VLAN_PCP'
242 actions.append(copy.deepcopy(action))
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700243 elif arg1 == "actionStripVlan":
244 stripVlan = {}
245 stripVlan['stripVlan'] = arg2 in ['True', 'true']
246 action['actionStripVlan'] = stripVlan
247 # action['actionType'] = 'ACTION_STRIP_VLAN'
248 actions.append(copy.deepcopy(action))
249 elif arg1 == "actionSetEthernetSrcAddr":
250 ethernetSrcAddr = {}
251 ethernetSrcAddr['value'] = arg2
252 setEthernetSrcAddr = {}
253 setEthernetSrcAddr['addr'] = ethernetSrcAddr
254 action['actionSetEthernetSrcAddr'] = setEthernetSrcAddr
255 # action['actionType'] = 'ACTION_SET_DL_SRC'
256 actions.append(copy.deepcopy(action))
257 elif arg1 == "actionSetEthernetDstAddr":
258 ethernetDstAddr = {}
259 ethernetDstAddr['value'] = arg2
260 setEthernetDstAddr = {}
261 setEthernetDstAddr['addr'] = ethernetDstAddr
262 action['actionSetEthernetDstAddr'] = setEthernetDstAddr
263 # action['actionType'] = 'ACTION_SET_DL_DST'
264 actions.append(copy.deepcopy(action))
265 elif arg1 == "actionSetIPv4SrcAddr":
266 IPv4SrcAddr = {}
267 IPv4SrcAddr['value'] = arg2
268 setIPv4SrcAddr = {}
269 setIPv4SrcAddr['addr'] = IPv4SrcAddr
270 action['actionSetIPv4SrcAddr'] = setIPv4SrcAddr
271 # action['actionType'] = 'ACTION_SET_NW_SRC'
272 actions.append(copy.deepcopy(action))
273 elif arg1 == "actionSetIPv4DstAddr":
274 IPv4DstAddr = {}
275 IPv4DstAddr['value'] = arg2
276 setIPv4DstAddr = {}
277 setIPv4DstAddr['addr'] = IPv4DstAddr
278 action['actionSetIPv4DstAddr'] = setIPv4DstAddr
279 # action['actionType'] = 'ACTION_SET_NW_DST'
280 actions.append(copy.deepcopy(action))
Pavlin Radoslavovad3a1e62013-07-09 13:30:16 -0700281 elif arg1 == "actionSetIpToS":
282 ipToS = {}
283 ipToS['ipToS'] = int(arg2, 0)
284 action['actionSetIpToS'] = ipToS
285 # action['actionType'] = 'ACTION_SET_NW_TOS'
286 actions.append(copy.deepcopy(action))
287 elif arg1 == "actionSetTcpUdpSrcPort":
288 tcpUdpSrcPort = {}
289 tcpUdpSrcPort['port'] = int(arg2, 0)
290 action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
291 # action['actionType'] = 'ACTION_SET_TP_SRC'
292 actions.append(copy.deepcopy(action))
293 elif arg1 == "actionSetTcpUdpDstPort":
294 tcpUdpDstPort = {}
295 tcpUdpDstPort['port'] = int(arg2, 0)
296 action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
297 # action['actionType'] = 'ACTION_SET_TP_DST'
298 actions.append(copy.deepcopy(action))
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700299 elif arg1 == "actionEnqueue":
300 # TODO: Implement ACTION_ENQUEUE
301 actionEnqueue = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700302 # actionEnqueue['queueId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700303 # enqueuePort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700304 # enqueuePort['value'] = int(arg3, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700305 # actionEnqueue['port'] = enqueuePort
306 # action['actionEnqueue'] = actionEnqueue
307 # # action['actionType'] = 'ACTION_ENQUEUE'
308 # actions.append(copy.deepcopy(action))
309 #
310 else:
311 log_error("ERROR: Unknown argument '%s'" % (arg1))
312 log_error(usage_msg)
313 exit(1)
314
Pavlin Radoslavov8a002d92013-03-13 20:20:43 -0700315 return {
316 'my_flow_id' : my_flow_id,
317 'my_installer_id' : my_installer_id,
318 'my_src_dpid' : my_src_dpid,
319 'my_src_port' : my_src_port,
320 'my_dst_dpid' : my_dst_dpid,
321 'my_dst_port' : my_dst_port,
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700322 'flowPathFlags' : flowPathFlags,
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800323 'idleTimeout' : idleTimeout,
324 'hardTimeout' : hardTimeout,
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800325 'priority' : priority,
Pavlin Radoslavov8a002d92013-03-13 20:20:43 -0700326 'match' : match,
327 'matchInPortEnabled' : matchInPortEnabled,
328 'actions' : actions,
329 'actionOutputEnabled' : actionOutputEnabled
330 }
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700331
332def compute_data_path(parsed_args):
333
334 my_src_dpid = parsed_args['my_src_dpid']
335 my_src_port = parsed_args['my_src_port']
336 my_dst_dpid = parsed_args['my_dst_dpid']
337 my_dst_port = parsed_args['my_dst_port']
338
339 # Compute the shortest path
340 data_path = shortest_path(my_src_dpid, my_src_port, my_dst_dpid, my_dst_port)
341
342 debug("Data Path: %s" % data_path)
343 return data_path
344
345def compute_flow_path(parsed_args, data_path):
346
347 my_flow_id = parsed_args['my_flow_id']
348 my_installer_id = parsed_args['my_installer_id']
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700349 myFlowPathFlags = parsed_args['flowPathFlags']
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800350 myIdleTimeout = parsed_args['idleTimeout']
351 myHardTimeout = parsed_args['hardTimeout']
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800352 myPriority = parsed_args['priority']
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700353 match = parsed_args['match']
354 matchInPortEnabled = parsed_args['matchInPortEnabled']
355 actions = parsed_args['actions']
356 actionOutputEnabled = parsed_args['actionOutputEnabled']
357 my_data_path = copy.deepcopy(data_path)
358
359 flow_id = {}
360 flow_id['value'] = my_flow_id
361 installer_id = {}
362 installer_id['value'] = my_installer_id
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700363 flowPathFlags = {}
364 flowPathFlags['flags'] = myFlowPathFlags
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700365
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700366 flowEntryActions = {}
367
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700368 flow_path = {}
369 flow_path['flowId'] = flow_id
370 flow_path['installerId'] = installer_id
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700371 # NOTE: The 'flowPathType' might be rewritten later
372 flow_path['flowPathType'] = 'FP_TYPE_EXPLICIT_PATH'
Pavlin Radoslavov7d4a40e2013-10-27 23:39:40 -0700373 flow_path['flowPathUserState'] = 'FP_USER_ADD'
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700374 flow_path['flowPathFlags'] = flowPathFlags
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800375 flow_path['idleTimeout'] = myIdleTimeout
376 flow_path['hardTimeout'] = myHardTimeout
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800377 flow_path['priority'] = myPriority
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700378
Pavlin Radoslavov67b3ef32013-04-03 02:44:48 -0700379 if (len(match) > 0):
380 flow_path['flowEntryMatch'] = copy.deepcopy(match)
381
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700382 #
383 # Add the match conditions to each flow entry
384 #
385 if (len(match) > 0) or matchInPortEnabled:
386 idx = 0
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700387 while idx < len(my_data_path['flowEntries']):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700388 if matchInPortEnabled:
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700389 inPort = my_data_path['flowEntries'][idx]['inPort']
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700390 match['inPort'] = copy.deepcopy(inPort)
391 # match['matchInPort'] = True
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700392 my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700393 idx = idx + 1
394
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700395
396 if (len(actions) > 0):
397 flowEntryActions['actions'] = copy.deepcopy(actions)
398 flow_path['flowEntryActions'] = flowEntryActions
399
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700400 #
401 # Set the actions for each flow entry
402 # NOTE: The actions from the command line are aplied
403 # ONLY to the first flow entry.
404 #
405 # If ACTION_OUTPUT action is enabled, then apply it
406 # to each flow entry.
407 #
408 if (len(actions) > 0) or actionOutputEnabled:
409 idx = 0
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700410 while idx < len(my_data_path['flowEntries']):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700411 if idx > 0:
412 actions = [] # Reset the actions for all but first entry
413 action = {}
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700414 outPort = my_data_path['flowEntries'][idx]['outPort']
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700415 actionOutput = {}
416 actionOutput['port'] = copy.deepcopy(outPort)
417 # actionOutput['maxLen'] = 0 # TODO: not used for now
418 action['actionOutput'] = copy.deepcopy(actionOutput)
419 # action['actionType'] = 'ACTION_OUTPUT'
420 actions.append(copy.deepcopy(action))
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700421 flowEntryActions = {}
422 flowEntryActions['actions'] = copy.deepcopy(actions)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700423
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700424 my_data_path['flowEntries'][idx]['flowEntryActions'] = flowEntryActions
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700425 idx = idx + 1
426
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700427 flow_path['dataPath'] = my_data_path
428 debug("Flow Path: %s" % flow_path)
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700429 return flow_path
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800430
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700431def exec_monitoring_by_onos(parsed_args):
432 idx = 0
433 while idx < len(parsed_args):
434 data_path = {}
435 src_dpid = {}
436 src_port = {}
437 dst_dpid = {}
438 dst_port = {}
439 src_switch_port = {}
440 dst_switch_port = {}
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700441 flow_entries = []
442
443 src_dpid['value'] = parsed_args[idx]['my_src_dpid']
444 src_port['value'] = parsed_args[idx]['my_src_port']
445 dst_dpid['value'] = parsed_args[idx]['my_dst_dpid']
446 dst_port['value'] = parsed_args[idx]['my_dst_port']
447 src_switch_port['dpid'] = src_dpid
448 src_switch_port['port'] = src_port
449 dst_switch_port['dpid'] = dst_dpid
450 dst_switch_port['port'] = dst_port
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700451
452 data_path['srcPort'] = copy.deepcopy(src_switch_port)
453 data_path['dstPort'] = copy.deepcopy(dst_switch_port)
454 data_path['flowEntries'] = copy.deepcopy(flow_entries)
455
456 #
457 # XXX: Explicitly disable the InPort matching, and
458 # the Output action, because they get in the way
459 # during the compute_flow_path() processing.
460 #
461 parsed_args[idx]['matchInPortEnabled'] = False
462 parsed_args[idx]['actionOutputEnabled'] = False
463
464 flow_path = compute_flow_path(parsed_args[idx], data_path)
Pavlin Radoslavovd28cf7c2013-10-26 11:27:43 -0700465 flow_path['flowPathType'] = 'FP_TYPE_SHORTEST_PATH'
466
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700467 add_shortest_path_flow(flow_path)
468
469 idx = idx + 1
470
471
472def exec_processing_by_script(parsed_args):
473 #
474 # Initialization
475 #
476 last_data_paths = []
477 idx = 0
478 while idx < len(parsed_args):
479 last_data_path = []
480 last_data_paths.append(copy.deepcopy(last_data_path))
481 idx = idx + 1
482
483 #
484 # Do the work: install and/or periodically monitor each flow
485 #
486 while True:
487 idx = 0
488 while idx < len(parsed_args):
489 last_data_path = last_data_paths[idx]
490 my_flow_id = parsed_args[idx]['my_flow_id']
491 data_path = compute_data_path(parsed_args[idx])
492 if data_path != last_data_path:
493 print_data_path(data_path)
494 if len(last_data_path) > 0:
495 delete_flow_path(my_flow_id)
496 if len(data_path) > 0:
497 flow_path = compute_flow_path(parsed_args[idx], data_path)
498 add_flow_path(flow_path)
499 last_data_paths[idx] = copy.deepcopy(data_path)
500 idx = idx + 1
501
502 if MonitoringEnabled != True:
503 break
504 time.sleep(1)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800505
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700506
507if __name__ == "__main__":
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800508 usage_msg = "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Flow Attributes] [Match Conditions] [Actions]\n" % (sys.argv[0])
Pavlin Radoslavov7be3bac2013-03-27 09:59:34 -0700509 usage_msg = usage_msg + "\n"
Pavlin Radoslavov051abb42013-12-05 17:24:50 -0800510 usage_msg = usage_msg + " <flow-id> The Flow ID, or -1 if it should be assigned by ONOS\n"
511 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700512 usage_msg = usage_msg + " Flags:\n"
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700513 usage_msg = usage_msg + " -m [monitorname] Monitor and maintain the installed shortest path(s)\n"
514 usage_msg = usage_msg + " If 'monitorname' is specified and is set to 'ONOS'\n"
Pavlin Radoslavovd3128c82013-11-11 14:58:00 -0800515 usage_msg = usage_msg + " (case insensitive), then the flow generation and\n"
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700516 usage_msg = usage_msg + " maintanenance is done by ONOS itself.\n"
517 usage_msg = usage_msg + " Otherwise, it is done by this script.\n"
518 usage_msg = usage_msg + " -f <filename> Read the flow(s) to install from a file\n"
519 usage_msg = usage_msg + " File format: one line per flow starting with <flow-id>\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700520 usage_msg = usage_msg + "\n"
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800521 usage_msg = usage_msg + " Flow Attributes:\n"
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700522 usage_msg = usage_msg + " flowPathFlags <Flags> (flag names separated by ',')\n"
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800523 usage_msg = usage_msg + " Known flags:\n"
Pavlin Radoslavov204b2862013-07-12 14:15:36 -0700524 usage_msg = usage_msg + " DISCARD_FIRST_HOP_ENTRY : Discard the first-hop flow entry\n"
525 usage_msg = usage_msg + " KEEP_ONLY_FIRST_HOP_ENTRY : Keep only the first-hop flow entry\n"
526 usage_msg = usage_msg + "\n"
Pavlin Radoslavovafbf1032014-02-04 10:37:52 -0800527 usage_msg = usage_msg + " idleTimeout <idleTimeoutInSeconds> (in the [0, 65535] interval;\n"
528 usage_msg = usage_msg + " default to 0: no timeout)\n"
529 usage_msg = usage_msg + " hardTimeout <hardTimeoutInSeconds> (in the [0, 65535] interval;\n"
530 usage_msg = usage_msg + " default to 0: no timeout)\n"
531 usage_msg = usage_msg + "\n"
532 usage_msg = usage_msg + " priority <flowPriority> (in the [0, 65535] interval; default to 32768)\n"
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800533 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700534 usage_msg = usage_msg + " Match Conditions:\n"
535 usage_msg = usage_msg + " matchInPort <True|False> (default to True)\n"
536 usage_msg = usage_msg + " matchSrcMac <source MAC address>\n"
537 usage_msg = usage_msg + " matchDstMac <destination MAC address>\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700538 usage_msg = usage_msg + " matchEthernetFrameType <Ethernet frame type>\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700539 usage_msg = usage_msg + " matchVlanId <VLAN ID>\n"
540 usage_msg = usage_msg + " matchVlanPriority <VLAN priority>\n"
Pavlin Radoslavovad3a1e62013-07-09 13:30:16 -0700541 usage_msg = usage_msg + " matchSrcIPv4Net <source IPv4 network address>\n"
542 usage_msg = usage_msg + " matchDstIPv4Net <destination IPv4 network address>\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700543 usage_msg = usage_msg + " matchIpProto <IP protocol>\n"
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800544 usage_msg = usage_msg + " matchIpToS <IP ToS> (DSCP field, 6 bits)\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700545 usage_msg = usage_msg + " matchSrcTcpUdpPort <source TCP/UDP port>\n"
546 usage_msg = usage_msg + " matchDstTcpUdpPort <destination TCP/UDP port>\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700547 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700548 usage_msg = usage_msg + " Actions:\n"
549 usage_msg = usage_msg + " actionOutput <True|False> (default to True)\n"
Pavlin Radoslavovc1bafd12013-07-12 17:00:35 -0700550 usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
551 usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
552 usage_msg = usage_msg + " actionStripVlan <True|False>\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700553 usage_msg = usage_msg + " actionSetEthernetSrcAddr <source MAC address>\n"
554 usage_msg = usage_msg + " actionSetEthernetDstAddr <destination MAC address>\n"
555 usage_msg = usage_msg + " actionSetIPv4SrcAddr <source IPv4 address>\n"
556 usage_msg = usage_msg + " actionSetIPv4DstAddr <destination IPv4 address>\n"
Pavlin Radoslavov4efa80f2013-12-10 11:18:24 -0800557 usage_msg = usage_msg + " actionSetIpToS <IP ToS> (DSCP field, 6 bits)\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700558 usage_msg = usage_msg + " actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
559 usage_msg = usage_msg + " actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700560 usage_msg = usage_msg + " Actions (not implemented yet):\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700561 usage_msg = usage_msg + " actionEnqueue <dummy argument>\n"
562
563 # app.debug = False;
564
565 # Usage info
566 if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
567 print(usage_msg)
568 exit(0)
569
570 #
571 # Check the flags
572 #
573 start_argv_index = 1
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700574 idx = 1
575 while idx < len(sys.argv):
576 arg1 = sys.argv[idx]
577 idx = idx + 1
578 if arg1 == "-m":
579 MonitoringEnabled = True
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700580 if idx < len(sys.argv):
581 arg2 = sys.argv[idx]
582 if arg2.lower() == "onos":
583 MonitoringByOnos = True
584 idx = idx + 1
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700585 start_argv_index = idx
586 elif arg1 == "-f":
587 if idx >= len(sys.argv):
588 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
589 log_error(error_arg)
590 log_error(usage_msg)
591 exit(1)
592 ReadFromFile = sys.argv[idx]
593 idx = idx + 1
594 start_argv_index = idx
595 else:
596 break;
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700597
598 #
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700599 # Read the arguments from a file or from the remaining command line options
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700600 #
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700601 my_lines = []
602 if len(ReadFromFile) > 0:
603 f = open(ReadFromFile, "rt")
604 my_line = f.readline()
605 while my_line:
606 if len(my_line.rstrip()) > 0 and my_line[0] != "#":
607 my_token_line = my_line.rstrip().split()
608 my_lines.append(my_token_line)
609 my_line = f.readline()
610 else:
611 my_lines.append(copy.deepcopy(sys.argv[start_argv_index:]))
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700612
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700613 #
614 # Initialization
615 #
616 last_data_paths = []
617 parsed_args = []
618 idx = 0
619 while idx < len(my_lines):
620 last_data_path = []
621 last_data_paths.append(copy.deepcopy(last_data_path))
622 #
623 # Parse the flow arguments
624 #
625 my_args = my_lines[idx]
626 parsed_args.append(copy.deepcopy(extract_flow_args(my_args)))
627 # Cleanup leftover state
628 my_flow_id = parsed_args[idx]['my_flow_id']
629 delete_flow_path(my_flow_id)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700630
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700631 idx = idx + 1
632
633 #
Pavlin Radoslavovb549f082013-03-29 04:28:27 -0700634 if MonitoringByOnos == True:
635 exec_monitoring_by_onos(parsed_args)
636 else:
637 exec_processing_by_script(parsed_args)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700638