1 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
24 LOG = logging.getLogger('ryu.lib.xflow.sflow')
32 def register_sflow_version(version):
33 def _register_sflow_version(cls):
34 sFlow._SFLOW_VERSIONS[version] = cls
36 return _register_sflow_version
39 super(sFlow, self).__init__()
43 (version,) = struct.unpack_from(cls._PACK_STR, buf)
45 cls_ = cls._SFLOW_VERSIONS.get(version, None)
47 return cls_.parser(buf)
52 @sFlow.register_sflow_version(SFLOW_V5)
53 class sFlowV5(object):
55 _PACK_STR_IPV4 = '!iiIIIII'
56 _PACK_STR_IPV6 = '!ii4IIIII'
59 _MIN_LEN_V4 = struct.calcsize(_PACK_STR_IPV4)
60 _MIN_LEN_V6 = struct.calcsize(_PACK_STR_IPV6)
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
71 self.samples_num = samples_num
72 self.samples = samples
76 (version, address_type) = struct.unpack_from(cls._PACK_STR, buf)
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
85 LOG.info("Unknown address_type. sFlowV5.address_type=%d",
89 (version, address_type, agent_address, sub_agent_id, sequence_number,
90 uptime, samples_num) = struct.unpack_from(pack_str, buf)
95 while len(buf) > offset:
96 sample = sFlowV5Sample.parser(buf, offset)
97 offset += sFlowV5Sample.MIN_LEN + sample.sample_length
98 samples.append(sample)
100 msg = cls(version, address_type, agent_address, sub_agent_id,
101 sequence_number, uptime, samples_num, samples)
106 class sFlowV5Sample(object):
108 MIN_LEN = struct.calcsize(_PACK_STR)
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
118 def parser(cls, buf, offset):
120 sample_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
123 enterprise_shiftbit = 12
125 sample_format = sampledata_format & format_mask
126 enterprise = sampledata_format >> enterprise_shiftbit
128 offset += cls.MIN_LEN
130 if sample_format == 1:
132 sample = sFlowV5FlowSample.parser(buf, offset)
133 elif sample_format == 2:
135 sample = sFlowV5CounterSample.parser(buf, offset)
138 # sample_format == 3 : Expanded Flow Sample
139 # sample_format == 4 : Expanded Counter Sample
140 LOG.info("Unknown format. sFlowV5Sample.sample_format=%d",
142 pack_str = '!%sc' % sample_length
143 sample = struct.unpack_from(pack_str, buf, offset)
145 msg = cls(enterprise, sample_format, sample_length, sample)
150 class sFlowV5FlowSample(object):
151 _PACK_STR = '!IIIIIIII'
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
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
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)
174 index_mask = 0xffffff
177 source_id_index = source_id & index_mask
178 source_id_type = source_id >> type_shiftbit
180 offset += struct.calcsize(cls._PACK_STR)
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)
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)
196 class sFlowV5FlowRecord(object):
198 MIN_LEN = struct.calcsize(_PACK_STR)
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
209 def parser(cls, buf, offset):
211 flow_data_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
214 enterprise_shiftbit = 12
216 flow_data_format = flowdata_format & format_mask
217 enterprise = flowdata_format >> enterprise_shiftbit
219 offset += cls.MIN_LEN
221 if flow_data_format == 1:
223 flow_data = sFlowV5RawPacketHeader.parser(buf, offset)
224 elif flow_data_format == 1001:
225 # Extended Switch Data
226 flow_data = sFlowV5ExtendedSwitchData.parser(buf, offset)
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",
245 pack_str = '!%sc' % flow_data_length
246 flow_data = struct.unpack_from(pack_str, buf, offset)
248 msg = cls(enterprise, flow_data_format, flow_data_length, flow_data)
253 class sFlowV5RawPacketHeader(object):
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
266 def parser(cls, buf, offset):
267 (header_protocol, frame_length, stripped,
268 header_size) = struct.unpack_from(cls._PACK_STR, buf, offset)
270 offset += struct.calcsize(cls._PACK_STR)
272 header_pack_str = '!%sc' % header_size
273 header = struct.unpack_from(header_pack_str, buf, offset)
275 msg = cls(header_protocol, frame_length, stripped, header_size, header)
279 class sFlowV5ExtendedSwitchData(object):
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
290 def parser(cls, buf, offset):
291 (src_vlan, src_priority, dest_vlan,
292 dest_priority) = struct.unpack_from(cls._PACK_STR, buf, offset)
294 msg = cls(src_vlan, src_priority, dest_vlan, dest_priority)
298 class sFlowV5CounterSample(object):
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
311 def parser(cls, buf, offset):
312 (sequence_number, source_id,
313 counters_records_num) = struct.unpack_from(cls._PACK_STR, buf, offset)
315 index_mask = 0xffffff
318 source_id_index = source_id & index_mask
319 source_id_type = source_id >> type_shiftbit
321 offset += struct.calcsize(cls._PACK_STR)
323 counters_records = []
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)
331 msg = cls(sequence_number, source_id_type, source_id_index,
332 counters_records_num, counters_records)
337 class sFlowV5CounterRecord(object):
339 MIN_LEN = struct.calcsize(_PACK_STR)
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
350 def parser(cls, buf, offset):
352 counter_data_length) = struct.unpack_from(cls._PACK_STR, buf, offset)
355 enterprise_shiftbit = 12
357 counter_data_format = counterdata_format & format_mask
358 enterprise = counterdata_format >> enterprise_shiftbit
360 offset += cls.MIN_LEN
362 if counter_data_format == 1:
363 # Generic Interface Counters
364 counter_data = sFlowV5GenericInterfaceCounters.parser(buf, offset)
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)
378 msg = cls(enterprise, counter_data_format,
379 counter_data_length, counter_data)
384 class sFlowV5GenericInterfaceCounters(object):
385 _PACK_STR = '!IIQIIQIIIIIIQIIIIII'
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
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
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)
424 ifAdminStatus_shiftbit = 1
426 ifOperStatus = ifStatus & ifStatus_mask
427 ifAdminStatus = ifStatus >> ifAdminStatus_shiftbit & ifStatus_mask
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)