backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / lib / xflow / sflow.py
1 # Copyright (C) 2013 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 logging
18
19 SFLOW_V2 = 0x00000002
20 SFLOW_V3 = 0x00000003
21 SFLOW_V4 = 0x00000004
22 SFLOW_V5 = 0x00000005
23
24 LOG = logging.getLogger('ryu.lib.xflow.sflow')
25
26
27 class sFlow(object):
28     _PACK_STR = '!i'
29     _SFLOW_VERSIONS = {}
30
31     @staticmethod
32     def register_sflow_version(version):
33         def _register_sflow_version(cls):
34             sFlow._SFLOW_VERSIONS[version] = cls
35             return cls
36         return _register_sflow_version
37
38     def __init__(self):
39         super(sFlow, self).__init__()
40
41     @classmethod
42     def parser(cls, buf):
43         (version,) = struct.unpack_from(cls._PACK_STR, buf)
44
45         cls_ = cls._SFLOW_VERSIONS.get(version, None)
46         if cls_:
47             return cls_.parser(buf)
48         else:
49             return None
50
51
52 @sFlow.register_sflow_version(SFLOW_V5)
53 class sFlowV5(object):
54     _PACK_STR = '!ii'
55     _PACK_STR_IPV4 = '!iiIIIII'
56     _PACK_STR_IPV6 = '!ii4IIIII'
57     _AGENT_IPTYPE_V4 = 1
58     _AGENT_IPTYPE_V6 = 2
59     _MIN_LEN_V4 = struct.calcsize(_PACK_STR_IPV4)
60     _MIN_LEN_V6 = struct.calcsize(_PACK_STR_IPV6)
61
62     def __init__(self, version, address_type, agent_address, sub_agent_id,
63                  sequence_number, uptime, samples_num, samples):
64         super(sFlowV5, self).__init__()
65         self.version = version
66         self.address_type = address_type
67         self.agent_address = agent_address
68         self.sub_agent_id = sub_agent_id
69         self.sequence_number = sequence_number
70         self.uptime = uptime
71         self.samples_num = samples_num
72         self.samples = samples
73
74     @classmethod
75     def parser(cls, buf):
76         (version, address_type) = struct.unpack_from(cls._PACK_STR, buf)
77
78         if address_type == cls._AGENT_IPTYPE_V4:
79             pack_str = cls._PACK_STR_IPV4
80             min_len = cls._MIN_LEN_V4
81         elif address_type == cls._AGENT_IPTYPE_V6:
82             pack_str = cls._PACK_STR_IPV6
83             min_len = cls._MIN_LEN_V6
84         else:
85             LOG.info("Unknown address_type. sFlowV5.address_type=%d",
86                      address_type)
87             return None
88
89         (version, address_type, agent_address, sub_agent_id, sequence_number,
90          uptime, samples_num) = struct.unpack_from(pack_str, buf)
91         offset = min_len
92
93         samples = []
94
95         while len(buf) > offset:
96             sample = sFlowV5Sample.parser(buf, offset)
97             offset += sFlowV5Sample.MIN_LEN + sample.sample_length
98             samples.append(sample)
99
100         msg = cls(version, address_type, agent_address, sub_agent_id,
101                   sequence_number, uptime, samples_num, samples)
102
103         return msg
104
105
106 class sFlowV5Sample(object):
107     _PACK_STR = '!II'
108     MIN_LEN = struct.calcsize(_PACK_STR)
109
110     def __init__(self, enterprise, sample_format, sample_length, sample):
111         super(sFlowV5Sample, self).__init__()
112         self.enterprise = enterprise
113         self.sample_format = sample_format
114         self.sample_length = sample_length
115         self.sample = sample
116
117     @classmethod
118     def parser(cls, buf, offset):
119         (sampledata_format,
120          sample_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
121
122         format_mask = 0xfff
123         enterprise_shiftbit = 12
124
125         sample_format = sampledata_format & format_mask
126         enterprise = sampledata_format >> enterprise_shiftbit
127
128         offset += cls.MIN_LEN
129
130         if sample_format == 1:
131             # Flow Sample
132             sample = sFlowV5FlowSample.parser(buf, offset)
133         elif sample_format == 2:
134             # Counter Sample
135             sample = sFlowV5CounterSample.parser(buf, offset)
136         else:
137             # TODO:
138             # sample_format == 3    : Expanded Flow Sample
139             # sample_format == 4    : Expanded Counter Sample
140             LOG.info("Unknown format. sFlowV5Sample.sample_format=%d",
141                      sample_format)
142             pack_str = '!%sc' % sample_length
143             sample = struct.unpack_from(pack_str, buf, offset)
144
145         msg = cls(enterprise, sample_format, sample_length, sample)
146
147         return msg
148
149
150 class sFlowV5FlowSample(object):
151     _PACK_STR = '!IIIIIIII'
152
153     def __init__(self, sequence_number, source_id_type, source_id_index,
154                  sampling_rate, sample_pool, drops, input_if, output_if,
155                  flow_records_num, flow_records):
156         super(sFlowV5FlowSample, self).__init__()
157         self.sequence_number = sequence_number
158         self.source_id_type = source_id_type
159         self.source_id_index = source_id_index
160         self.sampling_rate = sampling_rate
161         self.sample_pool = sample_pool
162         self.drops = drops
163         self.input_if = input_if
164         self.output_if = output_if
165         self.flow_records_num = flow_records_num
166         self.flow_records = flow_records
167
168     @classmethod
169     def parser(cls, buf, offset):
170         (sequence_number, source_id, sampling_rate,
171          sample_pool, drops, input_if, output_if,
172          flow_records_num) = struct.unpack_from(cls._PACK_STR, buf, offset)
173
174         index_mask = 0xffffff
175         type_shiftbit = 24
176
177         source_id_index = source_id & index_mask
178         source_id_type = source_id >> type_shiftbit
179
180         offset += struct.calcsize(cls._PACK_STR)
181
182         flow_records = []
183
184         for i in range(flow_records_num):
185             flow_record = sFlowV5FlowRecord.parser(buf, offset)
186             offset += sFlowV5FlowRecord.MIN_LEN + flow_record.flow_data_length
187             flow_records.append(flow_record)
188
189         msg = cls(sequence_number, source_id_type, source_id_index,
190                   sampling_rate, sample_pool, drops, input_if, output_if,
191                   flow_records_num, flow_records)
192
193         return msg
194
195
196 class sFlowV5FlowRecord(object):
197     _PACK_STR = '!II'
198     MIN_LEN = struct.calcsize(_PACK_STR)
199
200     def __init__(self, enterprise, flow_data_format,
201                  flow_data_length, flow_data):
202         super(sFlowV5FlowRecord, self).__init__()
203         self.enterprise = enterprise
204         self.flow_data_format = flow_data_format
205         self.flow_data_length = flow_data_length
206         self.flow_data = flow_data
207
208     @classmethod
209     def parser(cls, buf, offset):
210         (flowdata_format,
211          flow_data_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
212
213         format_mask = 0xfff
214         enterprise_shiftbit = 12
215
216         flow_data_format = flowdata_format & format_mask
217         enterprise = flowdata_format >> enterprise_shiftbit
218
219         offset += cls.MIN_LEN
220
221         if flow_data_format == 1:
222             # Raw Packet Header
223             flow_data = sFlowV5RawPacketHeader.parser(buf, offset)
224         elif flow_data_format == 1001:
225             # Extended Switch Data
226             flow_data = sFlowV5ExtendedSwitchData.parser(buf, offset)
227         else:
228             # TODO:
229             # flow_data_format == 2    : Ethernet Frame Data
230             # flow_data_format == 3    : IPv4 Data
231             # flow_data_format == 4    : IPv6 Data
232             # flow_data_format == 1002 : Extended Router Data
233             # flow_data_format == 1003 : Extended Gateway Data
234             # flow_data_format == 1004 : Extended User Data
235             # flow_data_format == 1005 : Extended Url Data
236             # flow_data_format == 1006 : Extended MPLS Data
237             # flow_data_format == 1007 : Extended NAT Data
238             # flow_data_format == 1008 : Extended MPLS Tunnel
239             # flow_data_format == 1009 : Extended MPLS VC
240             # flow_data_format == 1010 : Extended MPLS FEC
241             # flow_data_format == 1011 : Extended MPLS LVP FEC
242             # flow_data_format == 1012 : Extended VLAN tunnel
243             LOG.info("Unknown format. sFlowV5FlowRecord.flow_data_format=%d",
244                      flow_data_format)
245             pack_str = '!%sc' % flow_data_length
246             flow_data = struct.unpack_from(pack_str, buf, offset)
247
248         msg = cls(enterprise, flow_data_format, flow_data_length, flow_data)
249
250         return msg
251
252
253 class sFlowV5RawPacketHeader(object):
254     _PACK_STR = '!iIII'
255
256     def __init__(self, header_protocol, frame_length, stripped,
257                  header_size, header):
258         super(sFlowV5RawPacketHeader, self).__init__()
259         self.header_protocol = header_protocol
260         self.frame_length = frame_length
261         self.stripped = stripped
262         self.header_size = header_size
263         self.header = header
264
265     @classmethod
266     def parser(cls, buf, offset):
267         (header_protocol, frame_length, stripped,
268          header_size) = struct.unpack_from(cls._PACK_STR, buf, offset)
269
270         offset += struct.calcsize(cls._PACK_STR)
271
272         header_pack_str = '!%sc' % header_size
273         header = struct.unpack_from(header_pack_str, buf, offset)
274
275         msg = cls(header_protocol, frame_length, stripped, header_size, header)
276         return msg
277
278
279 class sFlowV5ExtendedSwitchData(object):
280     _PACK_STR = '!IIII'
281
282     def __init__(self, src_vlan, src_priority, dest_vlan, dest_priority):
283         super(sFlowV5ExtendedSwitchData, self).__init__()
284         self.src_vlan = src_vlan
285         self.src_priority = src_priority
286         self.dest_vlan = dest_vlan
287         self.dest_priority = dest_priority
288
289     @classmethod
290     def parser(cls, buf, offset):
291         (src_vlan, src_priority, dest_vlan,
292          dest_priority) = struct.unpack_from(cls._PACK_STR, buf, offset)
293
294         msg = cls(src_vlan, src_priority, dest_vlan, dest_priority)
295         return msg
296
297
298 class sFlowV5CounterSample(object):
299     _PACK_STR = '!III'
300
301     def __init__(self, sequence_number, source_id_type, source_id_index,
302                  counters_records_num, counters_records):
303         super(sFlowV5CounterSample, self).__init__()
304         self.sequence_number = sequence_number
305         self.source_id_type = source_id_type
306         self.source_id_index = source_id_index
307         self.counters_records_num = counters_records_num
308         self.counters_records = counters_records
309
310     @classmethod
311     def parser(cls, buf, offset):
312         (sequence_number, source_id,
313          counters_records_num) = struct.unpack_from(cls._PACK_STR, buf, offset)
314
315         index_mask = 0xffffff
316         type_shiftbit = 24
317
318         source_id_index = source_id & index_mask
319         source_id_type = source_id >> type_shiftbit
320
321         offset += struct.calcsize(cls._PACK_STR)
322
323         counters_records = []
324
325         for i in range(counters_records_num):
326             counter_record = sFlowV5CounterRecord.parser(buf, offset)
327             offset += sFlowV5CounterRecord.MIN_LEN
328             offset += counter_record.counter_data_length
329             counters_records.append(counter_record)
330
331         msg = cls(sequence_number, source_id_type, source_id_index,
332                   counters_records_num, counters_records)
333
334         return msg
335
336
337 class sFlowV5CounterRecord(object):
338     _PACK_STR = '!II'
339     MIN_LEN = struct.calcsize(_PACK_STR)
340
341     def __init__(self, enterprise, counter_data_format,
342                  counter_data_length, counter_data):
343         super(sFlowV5CounterRecord, self).__init__()
344         self.enterprise = enterprise
345         self.counter_data_format = counter_data_format
346         self.counter_data_length = counter_data_length
347         self.counter_data = counter_data
348
349     @classmethod
350     def parser(cls, buf, offset):
351         (counterdata_format,
352          counter_data_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
353
354         format_mask = 0xfff
355         enterprise_shiftbit = 12
356
357         counter_data_format = counterdata_format & format_mask
358         enterprise = counterdata_format >> enterprise_shiftbit
359
360         offset += cls.MIN_LEN
361
362         if counter_data_format == 1:
363             # Generic Interface Counters
364             counter_data = sFlowV5GenericInterfaceCounters.parser(buf, offset)
365         else:
366             # TODO:
367             # counter_data_format == 2    : Ethernet Interface Counters
368             # counter_data_format == 3    : Token Ring Counters
369             # counter_data_format == 4    : 100 BaseVG Interface Counters
370             # counter_data_format == 5    : VLAN Counters
371             # counter_data_format == 1001 : Processor Information
372             LOG.info("Unknown format. " +
373                      "sFlowV5CounterRecord.counter_data_format=%d"
374                      % counter_data_format)
375             pack_str = '!%sc' % counter_data_length
376             counter_data = struct.unpack_from(pack_str, buf, offset)
377
378         msg = cls(enterprise, counter_data_format,
379                   counter_data_length, counter_data)
380
381         return msg
382
383
384 class sFlowV5GenericInterfaceCounters(object):
385     _PACK_STR = '!IIQIIQIIIIIIQIIIIII'
386
387     def __init__(self, ifIndex, ifType, ifSpeed, ifDirection,
388                  ifAdminStatus, ifOperStatus, ifInOctets, ifInUcastPkts,
389                  ifInMulticastPkts, ifInBroadcastPkts, ifInDiscards,
390                  ifInErrors, ifInUnknownProtos, ifOutOctets,
391                  ifOutUcastPkts, ifOutMulticastPkts, ifOutBroadcastPkts,
392                  ifOutDiscards, ifOutErrors, ifPromiscuousMode):
393         super(sFlowV5GenericInterfaceCounters, self).__init__()
394         self.ifIndex = ifIndex
395         self.ifType = ifType
396         self.ifSpeed = ifSpeed
397         self.ifDirection = ifDirection
398         self.ifAdminStatus = ifAdminStatus
399         self.ifOperStatus = ifOperStatus
400         self.ifInOctets = ifInOctets
401         self.ifInUcastPkts = ifInUcastPkts
402         self.ifInMulticastPkts = ifInMulticastPkts
403         self.ifInBroadcastPkts = ifInBroadcastPkts
404         self.ifInDiscards = ifInDiscards
405         self.ifInErrors = ifInErrors
406         self.ifInUnknownProtos = ifInUnknownProtos
407         self.ifOutOctets = ifOutOctets
408         self.ifOutUcastPkts = ifOutUcastPkts
409         self.ifOutMulticastPkts = ifOutMulticastPkts
410         self.ifOutBroadcastPkts = ifOutBroadcastPkts
411         self.ifOutDiscards = ifOutDiscards
412         self.ifOutErrors = ifOutErrors
413         self.ifPromiscuousMode = ifPromiscuousMode
414
415     @classmethod
416     def parser(cls, buf, offset):
417         (ifIndex, ifType, ifSpeed, ifDirection, ifStatus, ifInOctets,
418          ifInUcastPkts, ifInMulticastPkts, ifInBroadcastPkts, ifInDiscards,
419          ifInErrors, ifInUnknownProtos, ifOutOctets, ifOutUcastPkts,
420          ifOutMulticastPkts, ifOutBroadcastPkts, ifOutDiscards, ifOutErrors,
421          ifPromiscuousMode,) = struct.unpack_from(cls._PACK_STR, buf, offset)
422
423         ifStatus_mask = 0x1
424         ifAdminStatus_shiftbit = 1
425
426         ifOperStatus = ifStatus & ifStatus_mask
427         ifAdminStatus = ifStatus >> ifAdminStatus_shiftbit & ifStatus_mask
428
429         msg = cls(ifIndex, ifType, ifSpeed, ifDirection, ifAdminStatus,
430                   ifOperStatus, ifInOctets, ifInUcastPkts,
431                   ifInMulticastPkts, ifInBroadcastPkts, ifInDiscards,
432                   ifInErrors, ifInUnknownProtos, ifOutOctets,
433                   ifOutUcastPkts, ifOutMulticastPkts, ifOutBroadcastPkts,
434                   ifOutDiscards, ifOutErrors, ifPromiscuousMode)
435
436         return msg