backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / ofctl_v1_0.py
1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #    http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 # implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 import struct
17 import socket
18 import logging
19
20 from ryu.ofproto import ofproto_v1_0
21 from ryu.lib import ofctl_utils
22 from ryu.lib.mac import haddr_to_bin, haddr_to_str
23
24
25 LOG = logging.getLogger('ryu.lib.ofctl_v1_0')
26
27 DEFAULT_TIMEOUT = 1.0   # TODO:XXX
28
29 UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_0)
30 str_to_int = ofctl_utils.str_to_int
31
32
33 def to_actions(dp, acts):
34     actions = []
35     for a in acts:
36         action_type = a.get('type')
37         if action_type == 'OUTPUT':
38             port = UTIL.ofp_port_from_user(
39                 a.get('port', ofproto_v1_0.OFPP_NONE))
40             # NOTE: The reason of this magic number (0xffe5)
41             #       is because there is no good constant in of1.0.
42             #       The same value as OFPCML_MAX of of1.2 and of1.3 is used.
43             max_len = str_to_int(a.get('max_len', 0xffe5))
44             actions.append(dp.ofproto_parser.OFPActionOutput(port, max_len))
45         elif action_type == 'SET_VLAN_VID':
46             vlan_vid = str_to_int(a.get('vlan_vid', 0xffff))
47             actions.append(dp.ofproto_parser.OFPActionVlanVid(vlan_vid))
48         elif action_type == 'SET_VLAN_PCP':
49             vlan_pcp = str_to_int(a.get('vlan_pcp', 0))
50             actions.append(dp.ofproto_parser.OFPActionVlanPcp(vlan_pcp))
51         elif action_type == 'STRIP_VLAN':
52             actions.append(dp.ofproto_parser.OFPActionStripVlan())
53         elif action_type == 'SET_DL_SRC':
54             dl_src = haddr_to_bin(a.get('dl_src'))
55             actions.append(dp.ofproto_parser.OFPActionSetDlSrc(dl_src))
56         elif action_type == 'SET_DL_DST':
57             dl_dst = haddr_to_bin(a.get('dl_dst'))
58             actions.append(dp.ofproto_parser.OFPActionSetDlDst(dl_dst))
59         elif action_type == 'SET_NW_SRC':
60             nw_src = ipv4_to_int(a.get('nw_src'))
61             actions.append(dp.ofproto_parser.OFPActionSetNwSrc(nw_src))
62         elif action_type == 'SET_NW_DST':
63             nw_dst = ipv4_to_int(a.get('nw_dst'))
64             actions.append(dp.ofproto_parser.OFPActionSetNwDst(nw_dst))
65         elif action_type == 'SET_NW_TOS':
66             nw_tos = str_to_int(a.get('nw_tos', 0))
67             actions.append(dp.ofproto_parser.OFPActionSetNwTos(nw_tos))
68         elif action_type == 'SET_TP_SRC':
69             tp_src = str_to_int(a.get('tp_src', 0))
70             actions.append(dp.ofproto_parser.OFPActionSetTpSrc(tp_src))
71         elif action_type == 'SET_TP_DST':
72             tp_dst = str_to_int(a.get('tp_dst', 0))
73             actions.append(dp.ofproto_parser.OFPActionSetTpDst(tp_dst))
74         elif action_type == 'ENQUEUE':
75             port = UTIL.ofp_port_from_user(
76                 a.get('port', ofproto_v1_0.OFPP_NONE))
77             queue_id = UTIL.ofp_queue_from_user(a.get('queue_id', 0))
78             actions.append(dp.ofproto_parser.OFPActionEnqueue(port, queue_id))
79         else:
80             LOG.error('Unknown action type')
81
82     return actions
83
84
85 def actions_to_str(acts):
86     actions = []
87     for a in acts:
88         action_type = a.cls_action_type
89
90         if action_type == ofproto_v1_0.OFPAT_OUTPUT:
91             port = UTIL.ofp_port_to_user(a.port)
92             buf = 'OUTPUT:' + str(port)
93         elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_VID:
94             buf = 'SET_VLAN_VID:' + str(a.vlan_vid)
95         elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_PCP:
96             buf = 'SET_VLAN_PCP:' + str(a.vlan_pcp)
97         elif action_type == ofproto_v1_0.OFPAT_STRIP_VLAN:
98             buf = 'STRIP_VLAN'
99         elif action_type == ofproto_v1_0.OFPAT_SET_DL_SRC:
100             buf = 'SET_DL_SRC:' + haddr_to_str(a.dl_addr)
101         elif action_type == ofproto_v1_0.OFPAT_SET_DL_DST:
102             buf = 'SET_DL_DST:' + haddr_to_str(a.dl_addr)
103         elif action_type == ofproto_v1_0.OFPAT_SET_NW_SRC:
104             buf = 'SET_NW_SRC:' + \
105                   socket.inet_ntoa(struct.pack('!I', a.nw_addr))
106         elif action_type == ofproto_v1_0.OFPAT_SET_NW_DST:
107             buf = 'SET_NW_DST:' + \
108                   socket.inet_ntoa(struct.pack('!I', a.nw_addr))
109         elif action_type == ofproto_v1_0.OFPAT_SET_NW_TOS:
110             buf = 'SET_NW_TOS:' + str(a.tos)
111         elif action_type == ofproto_v1_0.OFPAT_SET_TP_SRC:
112             buf = 'SET_TP_SRC:' + str(a.tp)
113         elif action_type == ofproto_v1_0.OFPAT_SET_TP_DST:
114             buf = 'SET_TP_DST:' + str(a.tp)
115         elif action_type == ofproto_v1_0.OFPAT_ENQUEUE:
116             port = UTIL.ofp_port_to_user(a.port)
117             queue = UTIL.ofp_queue_to_user(a.queue_id)
118             buf = 'ENQUEUE:' + str(port) + ":" + str(queue)
119         elif action_type == ofproto_v1_0.OFPAT_VENDOR:
120             buf = 'VENDOR'
121         else:
122             buf = 'UNKNOWN'
123         actions.append(buf)
124
125     return actions
126
127
128 def ipv4_to_int(addr):
129     ip = addr.split('.')
130     assert len(ip) == 4
131     i = 0
132     for b in ip:
133         b = int(b)
134         i = (i << 8) | b
135     return i
136
137
138 def to_match(dp, attrs):
139     ofp = dp.ofproto
140
141     wildcards = ofp.OFPFW_ALL
142     in_port = 0
143     dl_src = 0
144     dl_dst = 0
145     dl_vlan = 0
146     dl_vlan_pcp = 0
147     dl_type = 0
148     nw_tos = 0
149     nw_proto = 0
150     nw_src = 0
151     nw_dst = 0
152     tp_src = 0
153     tp_dst = 0
154
155     for key, value in attrs.items():
156         if key == 'in_port':
157             in_port = UTIL.ofp_port_from_user(value)
158             wildcards &= ~ofp.OFPFW_IN_PORT
159         elif key == 'dl_src':
160             dl_src = haddr_to_bin(value)
161             wildcards &= ~ofp.OFPFW_DL_SRC
162         elif key == 'dl_dst':
163             dl_dst = haddr_to_bin(value)
164             wildcards &= ~ofp.OFPFW_DL_DST
165         elif key == 'dl_vlan':
166             dl_vlan = str_to_int(value)
167             wildcards &= ~ofp.OFPFW_DL_VLAN
168         elif key == 'dl_vlan_pcp':
169             dl_vlan_pcp = str_to_int(value)
170             wildcards &= ~ofp.OFPFW_DL_VLAN_PCP
171         elif key == 'dl_type':
172             dl_type = str_to_int(value)
173             wildcards &= ~ofp.OFPFW_DL_TYPE
174         elif key == 'nw_tos':
175             nw_tos = str_to_int(value)
176             wildcards &= ~ofp.OFPFW_NW_TOS
177         elif key == 'nw_proto':
178             nw_proto = str_to_int(value)
179             wildcards &= ~ofp.OFPFW_NW_PROTO
180         elif key == 'nw_src':
181             ip = value.split('/')
182             nw_src = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
183             mask = 32
184             if len(ip) == 2:
185                 mask = int(ip[1])
186                 assert 0 < mask <= 32
187             v = (32 - mask) << ofp.OFPFW_NW_SRC_SHIFT | \
188                 ~ofp.OFPFW_NW_SRC_MASK
189             wildcards &= v
190         elif key == 'nw_dst':
191             ip = value.split('/')
192             nw_dst = struct.unpack('!I', socket.inet_aton(ip[0]))[0]
193             mask = 32
194             if len(ip) == 2:
195                 mask = int(ip[1])
196                 assert 0 < mask <= 32
197             v = (32 - mask) << ofp.OFPFW_NW_DST_SHIFT | \
198                 ~ofp.OFPFW_NW_DST_MASK
199             wildcards &= v
200         elif key == 'tp_src':
201             tp_src = str_to_int(value)
202             wildcards &= ~ofp.OFPFW_TP_SRC
203         elif key == 'tp_dst':
204             tp_dst = str_to_int(value)
205             wildcards &= ~ofp.OFPFW_TP_DST
206         else:
207             LOG.error("unknown match name %s, %s, %d", key, value, len(key))
208
209     match = dp.ofproto_parser.OFPMatch(
210         wildcards, in_port, dl_src, dl_dst, dl_vlan, dl_vlan_pcp,
211         dl_type, nw_tos, nw_proto, nw_src, nw_dst, tp_src, tp_dst)
212
213     return match
214
215
216 def match_to_str(m):
217
218     match = {}
219
220     if ~m.wildcards & ofproto_v1_0.OFPFW_IN_PORT:
221         match['in_port'] = UTIL.ofp_port_to_user(m.in_port)
222
223     if ~m.wildcards & ofproto_v1_0.OFPFW_DL_SRC:
224         match['dl_src'] = haddr_to_str(m.dl_src)
225
226     if ~m.wildcards & ofproto_v1_0.OFPFW_DL_DST:
227         match['dl_dst'] = haddr_to_str(m.dl_dst)
228
229     if ~m.wildcards & ofproto_v1_0.OFPFW_DL_VLAN:
230         match['dl_vlan'] = m.dl_vlan
231
232     if ~m.wildcards & ofproto_v1_0.OFPFW_DL_VLAN_PCP:
233         match['dl_vlan_pcp'] = m.dl_vlan_pcp
234
235     if ~m.wildcards & ofproto_v1_0.OFPFW_DL_TYPE:
236         match['dl_type'] = m.dl_type
237
238     if ~m.wildcards & ofproto_v1_0.OFPFW_NW_TOS:
239         match['nw_tos'] = m.nw_tos
240
241     if ~m.wildcards & ofproto_v1_0.OFPFW_NW_PROTO:
242         match['nw_proto'] = m.nw_proto
243
244     if ~m.wildcards & ofproto_v1_0.OFPFW_NW_SRC_ALL:
245         match['nw_src'] = nw_src_to_str(m.wildcards, m.nw_src)
246
247     if ~m.wildcards & ofproto_v1_0.OFPFW_NW_DST_ALL:
248         match['nw_dst'] = nw_dst_to_str(m.wildcards, m.nw_dst)
249
250     if ~m.wildcards & ofproto_v1_0.OFPFW_TP_SRC:
251         match['tp_src'] = m.tp_src
252
253     if ~m.wildcards & ofproto_v1_0.OFPFW_TP_DST:
254         match['tp_dst'] = m.tp_dst
255
256     return match
257
258
259 def nw_src_to_str(wildcards, addr):
260     ip = socket.inet_ntoa(struct.pack('!I', addr))
261     mask = 32 - ((wildcards & ofproto_v1_0.OFPFW_NW_SRC_MASK) >>
262                  ofproto_v1_0.OFPFW_NW_SRC_SHIFT)
263     if mask == 32:
264         mask = 0
265     if mask:
266         ip += '/%d' % mask
267     return ip
268
269
270 def nw_dst_to_str(wildcards, addr):
271     ip = socket.inet_ntoa(struct.pack('!I', addr))
272     mask = 32 - ((wildcards & ofproto_v1_0.OFPFW_NW_DST_MASK) >>
273                  ofproto_v1_0.OFPFW_NW_DST_SHIFT)
274     if mask == 32:
275         mask = 0
276     if mask:
277         ip += '/%d' % mask
278     return ip
279
280
281 def get_desc_stats(dp, waiters):
282     stats = dp.ofproto_parser.OFPDescStatsRequest(dp, 0)
283     msgs = []
284     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
285     s = {}
286
287     for msg in msgs:
288         stats = msg.body
289         s = stats.to_jsondict()[stats.__class__.__name__]
290
291     return {str(dp.id): s}
292
293
294 def get_queue_stats(dp, waiters, port=None, queue_id=None):
295     if port is None:
296         port = dp.ofproto.OFPP_ALL
297     else:
298         port = str_to_int(port)
299
300     if queue_id is None:
301         queue_id = dp.ofproto.OFPQ_ALL
302     else:
303         queue_id = str_to_int(queue_id)
304
305     stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, port,
306                                                    queue_id)
307     msgs = []
308     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
309
310     s = []
311     for msg in msgs:
312         stats = msg.body
313         for stat in stats:
314             s.append({'port_no': stat.port_no,
315                       'queue_id': stat.queue_id,
316                       'tx_bytes': stat.tx_bytes,
317                       'tx_errors': stat.tx_errors,
318                       'tx_packets': stat.tx_packets})
319
320     return {str(dp.id): s}
321
322
323 def get_flow_stats(dp, waiters, flow=None):
324     flow = flow if flow else {}
325     match = to_match(dp, flow.get('match', {}))
326     table_id = UTIL.ofp_table_from_user(
327         flow.get('table_id', 0xff))
328     out_port = UTIL.ofp_port_from_user(
329         flow.get('out_port', dp.ofproto.OFPP_NONE))
330     # Note: OpenFlow does not allow to filter flow entries by priority,
331     # but for efficiency, ofctl provides the way to do it.
332     priority = str_to_int(flow.get('priority', -1))
333
334     stats = dp.ofproto_parser.OFPFlowStatsRequest(
335         dp, 0, match, table_id, out_port)
336
337     msgs = []
338     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
339
340     flows = []
341     for msg in msgs:
342         for stats in msg.body:
343             if 0 <= priority != stats.priority:
344                 continue
345
346             actions = actions_to_str(stats.actions)
347             match = match_to_str(stats.match)
348
349             s = {'priority': stats.priority,
350                  'cookie': stats.cookie,
351                  'idle_timeout': stats.idle_timeout,
352                  'hard_timeout': stats.hard_timeout,
353                  'actions': actions,
354                  'match': match,
355                  'byte_count': stats.byte_count,
356                  'duration_sec': stats.duration_sec,
357                  'duration_nsec': stats.duration_nsec,
358                  'packet_count': stats.packet_count,
359                  'table_id': UTIL.ofp_table_to_user(stats.table_id)}
360             flows.append(s)
361
362     return {str(dp.id): flows}
363
364
365 def get_aggregate_flow_stats(dp, waiters, flow=None):
366     flow = flow if flow else {}
367     match = to_match(dp, flow.get('match', {}))
368     table_id = UTIL.ofp_table_from_user(
369         flow.get('table_id', 0xff))
370     out_port = UTIL.ofp_port_from_user(
371         flow.get('out_port', dp.ofproto.OFPP_NONE))
372
373     stats = dp.ofproto_parser.OFPAggregateStatsRequest(
374         dp, 0, match, table_id, out_port)
375
376     msgs = []
377     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
378
379     flows = []
380     for msg in msgs:
381         stats = msg.body
382         for st in stats:
383             s = {'packet_count': st.packet_count,
384                  'byte_count': st.byte_count,
385                  'flow_count': st.flow_count}
386             flows.append(s)
387
388     return {str(dp.id): flows}
389
390
391 def get_table_stats(dp, waiters):
392     stats = dp.ofproto_parser.OFPTableStatsRequest(dp, 0)
393     ofp = dp.ofproto
394     msgs = []
395     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
396
397     match_convert = {ofp.OFPFW_IN_PORT: 'IN_PORT',
398                      ofp.OFPFW_DL_VLAN: 'DL_VLAN',
399                      ofp.OFPFW_DL_SRC: 'DL_SRC',
400                      ofp.OFPFW_DL_DST: 'DL_DST',
401                      ofp.OFPFW_DL_TYPE: 'DL_TYPE',
402                      ofp.OFPFW_NW_PROTO: 'NW_PROTO',
403                      ofp.OFPFW_TP_SRC: 'TP_SRC',
404                      ofp.OFPFW_TP_DST: 'TP_DST',
405                      ofp.OFPFW_NW_SRC_SHIFT: 'NW_SRC_SHIFT',
406                      ofp.OFPFW_NW_SRC_BITS: 'NW_SRC_BITS',
407                      ofp.OFPFW_NW_SRC_MASK: 'NW_SRC_MASK',
408                      ofp.OFPFW_NW_SRC: 'NW_SRC',
409                      ofp.OFPFW_NW_SRC_ALL: 'NW_SRC_ALL',
410                      ofp.OFPFW_NW_DST_SHIFT: 'NW_DST_SHIFT',
411                      ofp.OFPFW_NW_DST_BITS: 'NW_DST_BITS',
412                      ofp.OFPFW_NW_DST_MASK: 'NW_DST_MASK',
413                      ofp.OFPFW_NW_DST: 'NW_DST',
414                      ofp.OFPFW_NW_DST_ALL: 'NW_DST_ALL',
415                      ofp.OFPFW_DL_VLAN_PCP: 'DL_VLAN_PCP',
416                      ofp.OFPFW_NW_TOS: 'NW_TOS',
417                      ofp.OFPFW_ALL: 'ALL',
418                      ofp.OFPFW_ICMP_TYPE: 'ICMP_TYPE',
419                      ofp.OFPFW_ICMP_CODE: 'ICMP_CODE'}
420
421     tables = []
422     for msg in msgs:
423         stats = msg.body
424         for stat in stats:
425             wildcards = []
426             for k, v in match_convert.items():
427                 if (1 << k) & stat.wildcards:
428                     wildcards.append(v)
429             s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
430                  'name': stat.name.decode('utf-8'),
431                  'wildcards': wildcards,
432                  'max_entries': stat.max_entries,
433                  'active_count': stat.active_count,
434                  'lookup_count': stat.lookup_count,
435                  'matched_count': stat.matched_count}
436             tables.append(s)
437
438     return {str(dp.id): tables}
439
440
441 def get_port_stats(dp, waiters, port=None):
442     if port is None:
443         port = dp.ofproto.OFPP_NONE
444     else:
445         port = str_to_int(port)
446
447     stats = dp.ofproto_parser.OFPPortStatsRequest(
448         dp, 0, port)
449     msgs = []
450     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
451
452     ports = []
453     for msg in msgs:
454         for stats in msg.body:
455             s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
456                  'rx_packets': stats.rx_packets,
457                  'tx_packets': stats.tx_packets,
458                  'rx_bytes': stats.rx_bytes,
459                  'tx_bytes': stats.tx_bytes,
460                  'rx_dropped': stats.rx_dropped,
461                  'tx_dropped': stats.tx_dropped,
462                  'rx_errors': stats.rx_errors,
463                  'tx_errors': stats.tx_errors,
464                  'rx_frame_err': stats.rx_frame_err,
465                  'rx_over_err': stats.rx_over_err,
466                  'rx_crc_err': stats.rx_crc_err,
467                  'collisions': stats.collisions}
468             ports.append(s)
469
470     return {str(dp.id): ports}
471
472
473 def get_port_desc(dp, waiters):
474
475     stats = dp.ofproto_parser.OFPFeaturesRequest(dp)
476     msgs = []
477     ofctl_utils.send_stats_request(dp, stats, waiters, msgs, LOG)
478
479     descs = []
480     for msg in msgs:
481         stats = msg.ports
482         for stat in stats.values():
483             d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
484                  'hw_addr': stat.hw_addr,
485                  'name': stat.name.decode('utf-8'),
486                  'config': stat.config,
487                  'state': stat.state,
488                  'curr': stat.curr,
489                  'advertised': stat.advertised,
490                  'supported': stat.supported,
491                  'peer': stat.peer}
492             descs.append(d)
493
494     return {str(dp.id): descs}
495
496
497 def mod_flow_entry(dp, flow, cmd):
498     cookie = str_to_int(flow.get('cookie', 0))
499     priority = str_to_int(
500         flow.get('priority', dp.ofproto.OFP_DEFAULT_PRIORITY))
501     buffer_id = UTIL.ofp_buffer_from_user(
502         flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
503     out_port = UTIL.ofp_port_from_user(
504         flow.get('out_port', dp.ofproto.OFPP_NONE))
505     flags = str_to_int(flow.get('flags', 0))
506     idle_timeout = str_to_int(flow.get('idle_timeout', 0))
507     hard_timeout = str_to_int(flow.get('hard_timeout', 0))
508     actions = to_actions(dp, flow.get('actions', []))
509     match = to_match(dp, flow.get('match', {}))
510
511     flow_mod = dp.ofproto_parser.OFPFlowMod(
512         datapath=dp, match=match, cookie=cookie,
513         command=cmd, idle_timeout=idle_timeout,
514         hard_timeout=hard_timeout, priority=priority,
515         buffer_id=buffer_id, out_port=out_port,
516         flags=flags,
517         actions=actions)
518
519     ofctl_utils.send_msg(dp, flow_mod, LOG)
520
521
522 def delete_flow_entry(dp):
523     match = dp.ofproto_parser.OFPMatch(
524         dp.ofproto.OFPFW_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
525
526     flow_mod = dp.ofproto_parser.OFPFlowMod(
527         datapath=dp, match=match, cookie=0,
528         command=dp.ofproto.OFPFC_DELETE)
529
530     ofctl_utils.send_msg(dp, flow_mod, LOG)
531
532
533 def mod_port_behavior(dp, port_config):
534     port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
535     hw_addr = str(port_config.get('hw_addr'))
536     config = str_to_int(port_config.get('config', 0))
537     mask = str_to_int(port_config.get('mask', 0))
538     advertise = str_to_int(port_config.get('advertise'))
539
540     port_mod = dp.ofproto_parser.OFPPortMod(
541         dp, port_no, hw_addr, config, mask, advertise)
542
543     ofctl_utils.send_msg(dp, port_mod, LOG)