blob: 0ab68470e9531141b4943e5a139417ad05724b24 [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#
17# curl http://127.0.0.1:8080/wm/topology/route/00:00:00:00:00:00:0a:01/1/00:00:00:00:00:00:0a:04/1/json
18#
19
20## Global Var ##
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070021ControllerIP = "127.0.0.1"
22ControllerPort = 8080
23MonitoringEnabled = False
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070024ReadFromFile = ""
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080025
26DEBUG=0
27pp = pprint.PrettyPrinter(indent=4)
28
29app = Flask(__name__)
30
31## Worker Functions ##
32def log_error(txt):
33 print '%s' % (txt)
34
35def debug(txt):
36 if DEBUG:
37 print '%s' % (txt)
38
39# @app.route("/wm/topology/route/<srcdpid>/<srcport>/<destdpid>/<destport>/json")
40#
41# Sample output:
42# {'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'}]}
43#
44def shortest_path(v1, p1, v2, p2):
45 try:
46 command = "curl -s http://%s:%s/wm/topology/route/%s/%s/%s/%s/json" % (ControllerIP, ControllerPort, v1, p1, v2, p2)
47 debug("shortest_path %s" % command)
Pavlin Radoslavoveb2d5a22013-03-14 19:58:14 -070048 parsedResult = []
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080049
50 result = os.popen(command).read()
51 debug("result %s" % result)
52 if len(result) == 0:
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070053 log_error("No Path found from %s/%s to %s/%s" % (v1, p1, v2, p2))
54 else:
55 parsedResult = json.loads(result)
56 debug("parsed %s" % parsedResult)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080057
58 except:
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070059 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 -080060
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070061 return parsedResult
62
63def print_data_path(data_path):
64 if len(data_path) == 0:
65 return
66
67 srcSwitch = data_path['srcPort']['dpid']['value'];
68 srcPort = data_path['srcPort']['port']['value'];
69 dstSwitch = data_path['dstPort']['dpid']['value'];
70 dstPort = data_path['dstPort']['port']['value'];
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080071
72 print "DataPath: (src = %s/%s dst = %s/%s)" % (srcSwitch, srcPort, dstSwitch, dstPort);
73
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -070074 for f in data_path['flowEntries']:
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080075 inPort = f['inPort']['value'];
76 outPort = f['outPort']['value'];
77 dpid = f['dpid']['value']
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070078 print " FlowEntry: (%s, %s, %s)" % (inPort, dpid, outPort)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080079
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080080def add_flow_path(flow_path):
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070081 flow_path_json = json.dumps(flow_path)
82
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080083 try:
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070084 command = "curl -s -H 'Content-Type: application/json' -d '%s' http://%s:%s/wm/flow/add/json" % (flow_path_json, ControllerIP, ControllerPort)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -080085 debug("add_flow_path %s" % command)
86 result = os.popen(command).read()
87 debug("result %s" % result)
88 # parsedResult = json.loads(result)
89 # debug("parsed %s" % parsedResult)
90 except:
91 log_error("Controller IF has issue")
92 exit(1)
93
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -070094def delete_flow_path(flow_id):
95 command = "curl -s \"http://%s:%s/wm/flow/delete/%s/json\"" % (ControllerIP, ControllerPort, flow_id)
96 debug("delete_flow_path %s" % command)
97 result = os.popen(command).read()
98 debug("result %s" % result)
99 # parsedResult = json.loads(result)
100 # debug("parsed %s" % parsedResult)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700101
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700102def extract_flow_args(my_args):
103 # Check the arguments
104 if len(my_args) < 6:
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800105 log_error(usage_msg)
106 exit(1)
107
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700108 # Extract the mandatory arguments
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700109 my_flow_id = my_args[0]
110 my_installer_id = my_args[1]
111 my_src_dpid = my_args[2]
112 my_src_port = my_args[3]
113 my_dst_dpid = my_args[4]
114 my_dst_port = my_args[5]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700115
116 #
117 # Extract the "match" and "action" arguments
118 #
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700119 match = {}
120 matchInPortEnabled = True # NOTE: Enabled by default
121 actions = []
122 actionOutputEnabled = True # NOTE: Enabled by default
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700123 idx = 6
124 while idx < len(my_args):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700125 action = {}
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700126 arg1 = my_args[idx]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700127 idx = idx + 1
128 # Extract the second argument
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700129 if idx >= len(my_args):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700130 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
131 log_error(error_arg)
132 log_error(usage_msg)
133 exit(1)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700134 arg2 = my_args[idx]
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700135 idx = idx + 1
136
137 if arg1 == "matchInPort":
138 # Just mark whether inPort matching is enabled
139 matchInPortEnabled = arg2 in ['True', 'true']
140 # inPort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700141 # inPort['value'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700142 # match['inPort'] = inPort
143 ## match['matchInPort'] = True
144 elif arg1 == "matchSrcMac":
145 srcMac = {}
146 srcMac['value'] = arg2
147 match['srcMac'] = srcMac
148 # match['matchSrcMac'] = True
149 elif arg1 == "matchDstMac":
150 dstMac = {}
151 dstMac['value'] = arg2
152 match['dstMac'] = dstMac
153 # match['matchDstMac'] = True
154 elif arg1 == "matchVlanId":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700155 match['vlanId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700156 # match['matchVlanId'] = True
157 elif arg1 == "matchVlanPriority":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700158 match['vlanPriority'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700159 # match['matchVlanPriority'] = True
160 elif arg1 == "matchEthernetFrameType":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700161 match['ethernetFrameType'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700162 # match['matchEthernetFrameType'] = True
163 elif arg1 == "matchIpToS":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700164 match['ipToS'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700165 # match['matchIpToS'] = True
166 elif arg1 == "matchIpProto":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700167 match['ipProto'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700168 # match['matchIpProto'] = True
169 elif arg1 == "matchSrcIPv4Net":
170 srcIPv4Net = {}
171 srcIPv4Net['value'] = arg2
172 match['srcIPv4Net'] = srcIPv4Net
173 # match['matchSrcIPv4Net'] = True
174 elif arg1 == "matchDstIPv4Net":
175 dstIPv4Net = {}
176 dstIPv4Net['value'] = arg2
177 match['dstIPv4Net'] = dstIPv4Net
178 # match['matchDstIPv4Net'] = True
179 elif arg1 == "matchSrcTcpUdpPort":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700180 match['srcTcpUdpPort'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700181 # match['matchSrcTcpUdpPort'] = True
182 elif arg1 == "matchDstTcpUdpPort":
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700183 match['dstTcpUdpPort'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700184 # match['matchDstTcpUdpPort'] = True
185 elif arg1 == "actionOutput":
186 # Just mark whether ACTION_OUTPUT action is enabled
187 actionOutputEnabled = arg2 in ['True', 'true']
188 #
189 # TODO: Complete the implementation for ACTION_OUTPUT
190 # actionOutput = {}
191 # outPort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700192 # outPort['value'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700193 # actionOutput['port'] = outPort
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700194 # actionOutput['maxLen'] = int(arg3, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700195 # action['actionOutput'] = actionOutput
196 # # action['actionType'] = 'ACTION_OUTPUT'
197 # actions.append(action)
198 #
199 elif arg1 == "actionSetVlanId":
200 vlanId = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700201 vlanId['vlanId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700202 action['actionSetVlanId'] = vlanId
203 # action['actionType'] = 'ACTION_SET_VLAN_VID'
204 actions.append(copy.deepcopy(action))
205 elif arg1 == "actionSetVlanPriority":
206 vlanPriority = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700207 vlanPriority['vlanPriority'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700208 action['actionSetVlanPriority'] = vlanPriority
209 # action['actionType'] = 'ACTION_SET_VLAN_PCP'
210 actions.append(copy.deepcopy(action))
211 elif arg1 == "actionSetIpToS":
212 ipToS = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700213 ipToS['ipToS'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700214 action['actionSetIpToS'] = ipToS
215 # action['actionType'] = 'ACTION_SET_NW_TOS'
216 actions.append(copy.deepcopy(action))
217 elif arg1 == "actionSetTcpUdpSrcPort":
218 tcpUdpSrcPort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700219 tcpUdpSrcPort['port'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700220 action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
221 # action['actionType'] = 'ACTION_SET_TP_SRC'
222 actions.append(copy.deepcopy(action))
223 elif arg1 == "actionSetTcpUdpDstPort":
224 tcpUdpDstPort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700225 tcpUdpDstPort['port'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700226 action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
227 # action['actionType'] = 'ACTION_SET_TP_DST'
228 actions.append(copy.deepcopy(action))
229 elif arg1 == "actionStripVlan":
230 stripVlan = {}
231 stripVlan['stripVlan'] = arg2 in ['True', 'true']
232 action['actionStripVlan'] = stripVlan
233 # action['actionType'] = 'ACTION_STRIP_VLAN'
234 actions.append(copy.deepcopy(action))
235 elif arg1 == "actionSetEthernetSrcAddr":
236 ethernetSrcAddr = {}
237 ethernetSrcAddr['value'] = arg2
238 setEthernetSrcAddr = {}
239 setEthernetSrcAddr['addr'] = ethernetSrcAddr
240 action['actionSetEthernetSrcAddr'] = setEthernetSrcAddr
241 # action['actionType'] = 'ACTION_SET_DL_SRC'
242 actions.append(copy.deepcopy(action))
243 elif arg1 == "actionSetEthernetDstAddr":
244 ethernetDstAddr = {}
245 ethernetDstAddr['value'] = arg2
246 setEthernetDstAddr = {}
247 setEthernetDstAddr['addr'] = ethernetDstAddr
248 action['actionSetEthernetDstAddr'] = setEthernetDstAddr
249 # action['actionType'] = 'ACTION_SET_DL_DST'
250 actions.append(copy.deepcopy(action))
251 elif arg1 == "actionSetIPv4SrcAddr":
252 IPv4SrcAddr = {}
253 IPv4SrcAddr['value'] = arg2
254 setIPv4SrcAddr = {}
255 setIPv4SrcAddr['addr'] = IPv4SrcAddr
256 action['actionSetIPv4SrcAddr'] = setIPv4SrcAddr
257 # action['actionType'] = 'ACTION_SET_NW_SRC'
258 actions.append(copy.deepcopy(action))
259 elif arg1 == "actionSetIPv4DstAddr":
260 IPv4DstAddr = {}
261 IPv4DstAddr['value'] = arg2
262 setIPv4DstAddr = {}
263 setIPv4DstAddr['addr'] = IPv4DstAddr
264 action['actionSetIPv4DstAddr'] = setIPv4DstAddr
265 # action['actionType'] = 'ACTION_SET_NW_DST'
266 actions.append(copy.deepcopy(action))
267 elif arg1 == "actionEnqueue":
268 # TODO: Implement ACTION_ENQUEUE
269 actionEnqueue = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700270 # actionEnqueue['queueId'] = int(arg2, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700271 # enqueuePort = {}
Pavlin Radoslavov14748912013-03-12 15:44:56 -0700272 # enqueuePort['value'] = int(arg3, 0)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700273 # actionEnqueue['port'] = enqueuePort
274 # action['actionEnqueue'] = actionEnqueue
275 # # action['actionType'] = 'ACTION_ENQUEUE'
276 # actions.append(copy.deepcopy(action))
277 #
278 else:
279 log_error("ERROR: Unknown argument '%s'" % (arg1))
280 log_error(usage_msg)
281 exit(1)
282
Pavlin Radoslavov8a002d92013-03-13 20:20:43 -0700283 return {
284 'my_flow_id' : my_flow_id,
285 'my_installer_id' : my_installer_id,
286 'my_src_dpid' : my_src_dpid,
287 'my_src_port' : my_src_port,
288 'my_dst_dpid' : my_dst_dpid,
289 'my_dst_port' : my_dst_port,
290 'match' : match,
291 'matchInPortEnabled' : matchInPortEnabled,
292 'actions' : actions,
293 'actionOutputEnabled' : actionOutputEnabled
294 }
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700295
296def compute_data_path(parsed_args):
297
298 my_src_dpid = parsed_args['my_src_dpid']
299 my_src_port = parsed_args['my_src_port']
300 my_dst_dpid = parsed_args['my_dst_dpid']
301 my_dst_port = parsed_args['my_dst_port']
302
303 # Compute the shortest path
304 data_path = shortest_path(my_src_dpid, my_src_port, my_dst_dpid, my_dst_port)
305
306 debug("Data Path: %s" % data_path)
307 return data_path
308
309def compute_flow_path(parsed_args, data_path):
310
311 my_flow_id = parsed_args['my_flow_id']
312 my_installer_id = parsed_args['my_installer_id']
313 match = parsed_args['match']
314 matchInPortEnabled = parsed_args['matchInPortEnabled']
315 actions = parsed_args['actions']
316 actionOutputEnabled = parsed_args['actionOutputEnabled']
317 my_data_path = copy.deepcopy(data_path)
318
319 flow_id = {}
320 flow_id['value'] = my_flow_id
321 installer_id = {}
322 installer_id['value'] = my_installer_id
323
324 flow_path = {}
325 flow_path['flowId'] = flow_id
326 flow_path['installerId'] = installer_id
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700327
328 #
329 # Add the match conditions to each flow entry
330 #
331 if (len(match) > 0) or matchInPortEnabled:
332 idx = 0
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700333 while idx < len(my_data_path['flowEntries']):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700334 if matchInPortEnabled:
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700335 inPort = my_data_path['flowEntries'][idx]['inPort']
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700336 match['inPort'] = copy.deepcopy(inPort)
337 # match['matchInPort'] = True
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700338 my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700339 idx = idx + 1
340
341 #
342 # Set the actions for each flow entry
343 # NOTE: The actions from the command line are aplied
344 # ONLY to the first flow entry.
345 #
346 # If ACTION_OUTPUT action is enabled, then apply it
347 # to each flow entry.
348 #
349 if (len(actions) > 0) or actionOutputEnabled:
350 idx = 0
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700351 while idx < len(my_data_path['flowEntries']):
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700352 if idx > 0:
353 actions = [] # Reset the actions for all but first entry
354 action = {}
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700355 outPort = my_data_path['flowEntries'][idx]['outPort']
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700356 actionOutput = {}
357 actionOutput['port'] = copy.deepcopy(outPort)
358 # actionOutput['maxLen'] = 0 # TODO: not used for now
359 action['actionOutput'] = copy.deepcopy(actionOutput)
360 # action['actionType'] = 'ACTION_OUTPUT'
361 actions.append(copy.deepcopy(action))
362
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700363 my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
Pavlin Radoslavovf13923a2013-03-11 19:42:17 -0700364 idx = idx + 1
365
366
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700367 flow_path['dataPath'] = my_data_path
368 debug("Flow Path: %s" % flow_path)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800369
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700370 add_flow_path(flow_path)
Pavlin Radoslavovf4ad9892013-03-04 14:15:19 -0800371
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700372
373if __name__ == "__main__":
374 usage_msg = "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Match Conditions] [Actions]\n" % (sys.argv[0])
Pavlin Radoslavov7be3bac2013-03-27 09:59:34 -0700375 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700376 usage_msg = usage_msg + " Flags:\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700377 usage_msg = usage_msg + " -m Monitor and maintain the installed shortest path(s)\n"
378 usage_msg = usage_msg + " -f <filename> Read the flow(s) to install from a file\n"
379 usage_msg = usage_msg + " File format: one line per flow starting with <flow-id>\n"
380 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700381 usage_msg = usage_msg + " Match Conditions:\n"
382 usage_msg = usage_msg + " matchInPort <True|False> (default to True)\n"
383 usage_msg = usage_msg + " matchSrcMac <source MAC address>\n"
384 usage_msg = usage_msg + " matchDstMac <destination MAC address>\n"
385 usage_msg = usage_msg + " matchSrcIPv4Net <source IPv4 network address>\n"
386 usage_msg = usage_msg + " matchDstIPv4Net <destination IPv4 network address>\n"
387 usage_msg = usage_msg + " matchEthernetFrameType <Ethernet frame type>\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700388 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700389 usage_msg = usage_msg + " Match Conditions (not implemented yet):\n"
390 usage_msg = usage_msg + " matchVlanId <VLAN ID>\n"
391 usage_msg = usage_msg + " matchVlanPriority <VLAN priority>\n"
392 usage_msg = usage_msg + " matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
393 usage_msg = usage_msg + " matchIpProto <IP protocol>\n"
394 usage_msg = usage_msg + " matchSrcTcpUdpPort <source TCP/UDP port>\n"
395 usage_msg = usage_msg + " matchDstTcpUdpPort <destination TCP/UDP port>\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700396 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700397 usage_msg = usage_msg + " Actions:\n"
398 usage_msg = usage_msg + " actionOutput <True|False> (default to True)\n"
399 usage_msg = usage_msg + " actionSetEthernetSrcAddr <source MAC address>\n"
400 usage_msg = usage_msg + " actionSetEthernetDstAddr <destination MAC address>\n"
401 usage_msg = usage_msg + " actionSetIPv4SrcAddr <source IPv4 address>\n"
402 usage_msg = usage_msg + " actionSetIPv4DstAddr <destination IPv4 address>\n"
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700403 usage_msg = usage_msg + "\n"
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700404 usage_msg = usage_msg + " Actions (not implemented yet):\n"
405 usage_msg = usage_msg + " actionSetVlanId <VLAN ID>\n"
406 usage_msg = usage_msg + " actionSetVlanPriority <VLAN priority>\n"
407 usage_msg = usage_msg + " actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
408 usage_msg = usage_msg + " actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
409 usage_msg = usage_msg + " actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
410 usage_msg = usage_msg + " actionStripVlan <True|False>\n"
411 usage_msg = usage_msg + " actionEnqueue <dummy argument>\n"
412
413 # app.debug = False;
414
415 # Usage info
416 if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
417 print(usage_msg)
418 exit(0)
419
420 #
421 # Check the flags
422 #
423 start_argv_index = 1
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700424 idx = 1
425 while idx < len(sys.argv):
426 arg1 = sys.argv[idx]
427 idx = idx + 1
428 if arg1 == "-m":
429 MonitoringEnabled = True
430 start_argv_index = idx
431 elif arg1 == "-f":
432 if idx >= len(sys.argv):
433 error_arg = "ERROR: Missing or invalid '" + arg1 + "' argument"
434 log_error(error_arg)
435 log_error(usage_msg)
436 exit(1)
437 ReadFromFile = sys.argv[idx]
438 idx = idx + 1
439 start_argv_index = idx
440 else:
441 break;
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700442
443 #
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700444 # Read the arguments from a file or from the remaining command line options
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700445 #
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700446 my_lines = []
447 if len(ReadFromFile) > 0:
448 f = open(ReadFromFile, "rt")
449 my_line = f.readline()
450 while my_line:
451 if len(my_line.rstrip()) > 0 and my_line[0] != "#":
452 my_token_line = my_line.rstrip().split()
453 my_lines.append(my_token_line)
454 my_line = f.readline()
455 else:
456 my_lines.append(copy.deepcopy(sys.argv[start_argv_index:]))
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700457
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700458 #
459 # Initialization
460 #
461 last_data_paths = []
462 parsed_args = []
463 idx = 0
464 while idx < len(my_lines):
465 last_data_path = []
466 last_data_paths.append(copy.deepcopy(last_data_path))
467 #
468 # Parse the flow arguments
469 #
470 my_args = my_lines[idx]
471 parsed_args.append(copy.deepcopy(extract_flow_args(my_args)))
472 # Cleanup leftover state
473 my_flow_id = parsed_args[idx]['my_flow_id']
474 delete_flow_path(my_flow_id)
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700475
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700476 idx = idx + 1
477
478 #
479 # Do the work: install and/or periodically monitor each flow
480 #
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700481 while True:
Pavlin Radoslavov2a0bd8b2013-03-15 18:45:51 -0700482 idx = 0
483 while idx < len(parsed_args):
484 last_data_path = last_data_paths[idx]
485 my_flow_id = parsed_args[idx]['my_flow_id']
486 data_path = compute_data_path(parsed_args[idx])
487 if data_path != last_data_path:
488 print_data_path(data_path)
489 if len(last_data_path) > 0:
490 delete_flow_path(my_flow_id)
491 if len(data_path) > 0:
492 flow_path = compute_flow_path(parsed_args[idx], data_path)
493 add_flow_path(flow_path)
494 last_data_paths[idx] = copy.deepcopy(data_path)
495 idx = idx + 1
Pavlin Radoslavov3f3778a2013-03-13 08:16:57 -0700496
497 if MonitoringEnabled != True:
498 break
499 time.sleep(1)