backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / unit / lib / test_mrtlib.py
1 # Copyright (C) 2016 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 from __future__ import print_function
17
18 import bz2
19 import io
20 import logging
21 import os
22 import struct
23 import sys
24 import unittest
25
26 try:
27     import mock  # Python 2
28 except ImportError:
29     from unittest import mock  # Python 3
30
31 from nose.tools import eq_
32 from nose.tools import ok_
33
34 from ryu.lib import addrconv
35 from ryu.lib import mrtlib
36 from ryu.lib.packet import bgp
37 from ryu.lib.packet import ospf
38 from ryu.utils import binary_str
39
40
41 LOG = logging.getLogger(__name__)
42
43 MRT_DATA_DIR = os.path.join(
44     os.path.dirname(sys.modules[__name__].__file__), '../../packet_data/mrt/')
45
46
47 class TestMrtlib(unittest.TestCase):
48     """
49     Test case for ryu.lib.mrtlib.
50     """
51
52     def test_reader(self):
53         files = [
54             'rib.20161101.0000_pick.bz2',
55             'updates.20161101.0000.bz2',
56         ]
57
58         for f in files:
59             # print('\n*** testing mrtlib.Reader with %s ...' % f)
60             counter = 0
61             input_file = os.path.join(MRT_DATA_DIR, f)
62             for record in mrtlib.Reader(bz2.BZ2File(input_file, 'rb')):
63                 # print('* No.%d\n%s' % (counter, record))
64                 ok_(not isinstance(record, mrtlib.UnknownMrtRecord))
65                 counter += 1
66
67     def test_writer(self):
68         files = [
69             'rib.20161101.0000_pick.bz2',
70             'updates.20161101.0000.bz2',
71         ]
72
73         for f in files:
74             # print('\n*** testing mrtlib.Writer with %s ...' % f)
75             input_file = os.path.join(MRT_DATA_DIR, f)
76             input_buf = bz2.BZ2File(input_file, 'rb').read()
77             input_records = list(mrtlib.Reader(bz2.BZ2File(input_file, 'rb')))
78
79             counter = 0
80             f = io.BytesIO()
81             mrt_writer = mrtlib.Writer(f)
82             for record in input_records:
83                 # print('* No.%d\n%s' % (counter, record))
84                 mrt_writer.write(record)
85                 counter += 1
86
87             output_buf = f.getvalue()
88
89             eq_(binary_str(input_buf), binary_str(output_buf))
90
91             mrt_writer.close()
92
93             eq_(True, mrt_writer._f.closed)
94
95
96 class TestMrtlibMrtRecord(unittest.TestCase):
97     """
98     Test case for ryu.lib.mrtlib.MrtRecord.
99     """
100
101     def test_init_without_type_subtype(self):
102         type_ = mrtlib.MrtRecord.TYPE_TABLE_DUMP
103         subtype = mrtlib.TableDumpMrtRecord.SUBTYPE_AFI_IPv4
104
105         message = mrtlib.TableDumpAfiIPv4MrtMessage(
106             view_num=1,
107             seq_num=2,
108             prefix='192.168.1.0',
109             prefix_len=24,
110             status=1,
111             originated_time=0,
112             peer_ip='10.0.0.1',
113             peer_as=65000,
114             bgp_attributes=[],
115         )
116         record = mrtlib.TableDumpMrtRecord(message)
117
118         eq_(type_, record.type)
119         eq_(subtype, record.subtype)
120
121     def test_parse_pre_with_type_et(self):
122         buf = (
123             b'\x00\x00\x00\x00'  # timestamp
124             b'\x00\x11\x00\x00'  # type=TYPE_BGP4MP_ET(17), subtype
125             b'\x00\x00\x00\xaa'  # length
126         )
127
128         required_len = mrtlib.MrtRecord.parse_pre(buf)
129
130         eq_(0xaa + mrtlib.ExtendedTimestampMrtRecord.HEADER_SIZE,
131             required_len)
132
133
134 # Note: MrtCommonRecord is tested in TestMrtlibMrtRecord.
135 # class TestMrtlibMrtCommonRecord(unittest.TestCase):
136
137
138 class TestMrtlibExtendedTimestampMrtRecord(unittest.TestCase):
139     """
140     Test case for ryu.lib.mrtlib.ExtendedTimestampMrtRecord.
141     """
142
143     def test_parse_extended_header(self):
144         body = b'test'
145         buf = (
146             b'\x11\x11\x11\x11'  # ms_timestamp
147             + body
148         )
149
150         (headers,
151          rest) = mrtlib.ExtendedTimestampMrtRecord.parse_extended_header(buf)
152
153         ok_(isinstance(headers, list))
154         eq_(1, len(headers))
155         eq_(0x11111111, headers[0])
156         eq_(body, rest)
157
158     def test_serialize(self):
159         body = b'test'  # 4 bytes
160         buf = (
161             b'\x11\x11\x11\x11'  # timestamp
162             b'\x22\x22\x33\x33'  # type, subtype
163             b'\x00\x00\x00\x04'  # length=len(body)
164             b'\x44\x44\x44\x44'  # ms_timestamp
165             + body
166         )
167
168         message_mock = mock.MagicMock(spec=mrtlib.MrtMessage)
169         message_mock.serialize.return_value = body
170
171         record = mrtlib.ExtendedTimestampMrtRecord(
172             message=message_mock,
173             timestamp=0x11111111,
174             type_=0x2222, subtype=0x3333,
175             ms_timestamp=0x44444444,
176             length=0x00000004,
177         )
178
179         output = record.serialize()
180
181         eq_(buf, output)
182
183
184 class TestMrtlibUnknownMrtRecord(unittest.TestCase):
185     """
186     Test case for ryu.lib.mrtlib.UnknownMrtRecord.
187     """
188
189     def test_parse(self):
190         body = b'test'  # 4 bytes
191         buf = (
192             b'\x11\x11\x11\x11'  # timestamp
193             b'\x22\x22\x33\x33'  # type, subtype
194             b'\x00\x00\x00\x04'  # length=len(body)
195             + body
196         )
197
198         (record, rest) = mrtlib.MrtRecord.parse(buf)
199
200         eq_(0x11111111, record.timestamp)
201         eq_(0x2222, record.type)
202         eq_(0x3333, record.subtype)
203         eq_(0x00000004, record.length)
204         eq_(body, record.message.buf)
205         eq_(b'', rest)
206
207     def test_serialize(self):
208         body = b'test'  # 4 bytes
209         buf = (
210             b'\x11\x11\x11\x11'  # timestamp
211             b'\x22\x22\x33\x33'  # type, subtype
212             b'\x00\x00\x00\x04'  # length=len(body)
213             + body
214         )
215
216         message = mrtlib.UnknownMrtMessage(buf=body)
217         record = mrtlib.UnknownMrtRecord(
218             message=message,
219             timestamp=0x11111111,
220             type_=0x2222, subtype=0x3333,
221             length=0x00000004,
222         )
223
224         output = record.serialize()
225
226         eq_(buf, output)
227
228
229 class TestMrtlibOspf2MrtRecord(unittest.TestCase):
230     """
231     Test case for ryu.lib.mrtlib.Ospf2MrtRecord.
232     """
233
234     @mock.patch('ryu.lib.packet.ospf.ospf.parser')
235     def test_parse(self, mock_ospf_parser):
236         remote_ip = '10.0.0.1'
237         local_ip = '10.0.0.2'
238         body = b'test'  # 4 bytes
239         buf = (
240             b'\x11\x11\x11\x11'  # timestamp
241             b'\x00\x0b\x00\x00'  # type=TYPE_OSPFv2(11), subtype
242             b'\x00\x00\x00\x0c'  # length=len(remote_ip + local_ip + body)
243             + addrconv.ipv4.text_to_bin(remote_ip)  # remote_ip
244             + addrconv.ipv4.text_to_bin(local_ip)   # local_ip
245             + body               # ospf_message
246         )
247
248         mock_ospf_message = mock.MagicMock(spec=ospf.OSPFMessage)
249         mock_ospf_parser.return_value = (mock_ospf_message, None, '')
250
251         (record, rest) = mrtlib.MrtRecord.parse(buf)
252
253         eq_(0x11111111, record.timestamp)
254         eq_(mrtlib.MrtRecord.TYPE_OSPFv2, record.type)
255         eq_(0x0000, record.subtype)
256         eq_(0x0000000c, record.length)
257         eq_(remote_ip, record.message.remote_ip)
258         eq_(local_ip, record.message.local_ip)
259         eq_(mock_ospf_message, record.message.ospf_message)
260         eq_(b'', rest)
261
262     def test_serialize(self):
263         remote_ip = '10.0.0.1'
264         local_ip = '10.0.0.2'
265         body = b'test'  # 4 bytes
266         buf = (
267             b'\x11\x11\x11\x11'  # timestamp
268             b'\x00\x0b\x00\x00'  # type=TYPE_OSPFv2(11), subtype
269             b'\x00\x00\x00\x0c'  # length=len(remote_ip + local_ip + body)
270             + addrconv.ipv4.text_to_bin(remote_ip)  # remote_ip
271             + addrconv.ipv4.text_to_bin(local_ip)   # local_ip
272             + body               # ospf_message
273         )
274
275         mock_ospf_message = mock.MagicMock(spec=ospf.OSPFMessage)
276         mock_ospf_message.serialize.return_value = body
277
278         message = mrtlib.Ospf2MrtMessage(
279             remote_ip=remote_ip,
280             local_ip=local_ip,
281             ospf_message=mock_ospf_message,
282         )
283         record = mrtlib.Ospf2MrtRecord(
284             message=message,
285             timestamp=0x11111111,
286             # type_=None,
287             # subtype=None,
288             # length=None,
289         )
290
291         output = record.serialize()
292
293         eq_(buf, output)
294
295
296 class TestMrtlibTableDumpMrtRecord(unittest.TestCase):
297     """
298     Test case for ryu.lib.mrtlib.TableDumpMrtRecord.
299     """
300
301     @mock.patch('ryu.lib.packet.bgp._PathAttribute.parser')
302     def test_parse_afi_ipv4(self, mock_bgp_attr_parser):
303         prefix = '10.0.0.0'
304         peer_ip = '172.16.0.1'
305         body = b'test'  # 4 bytes
306         buf = (
307             b'\x11\x11\x11\x11'  # timestamp
308             b'\x00\x0c\x00\x01'  # type=TYPE_TABLE_DUMP(12),
309                                  # subtype=SUBTYPE_AFI_IPv4(1)
310             b'\x00\x00\x00\x1a'  # length=26
311             b'\x22\x22\x33\x33'  # view_num, seq_num
312             + addrconv.ipv4.text_to_bin(prefix) +  # prefix
313             b'\x18\x01'          # prefix_len=24, status=1
314             b'\x44\x44\x44\x44'  # originated_time
315             + addrconv.ipv4.text_to_bin(peer_ip) +  # peer_ip
316             b'\xfd\xe8\x00\x04'  # peer_as=65000, attr_len=len(body)
317             + body               # bgp_attributes
318         )
319
320         mock_bgp_attr = mock.MagicMock(spec=bgp._PathAttribute)
321         mock_bgp_attr_parser.return_value = (mock_bgp_attr, b'')
322
323         (record, rest) = mrtlib.MrtRecord.parse(buf)
324
325         eq_(0x11111111, record.timestamp)
326         eq_(mrtlib.MrtRecord.TYPE_TABLE_DUMP, record.type)
327         eq_(mrtlib.TableDumpMrtRecord.SUBTYPE_AFI_IPv4, record.subtype)
328         eq_(0x0000001a, record.length)
329         eq_(0x2222, record.message.view_num)
330         eq_(0x3333, record.message.seq_num)
331         eq_(prefix, record.message.prefix)
332         eq_(24, record.message.prefix_len)
333         eq_(1, record.message.status)
334         eq_(0x44444444, record.message.originated_time)
335         eq_(peer_ip, record.message.peer_ip)
336         eq_(65000, record.message.peer_as)
337         eq_(0x0004, record.message.attr_len)
338         eq_([mock_bgp_attr], record.message.bgp_attributes)
339         eq_(b'', rest)
340
341     def test_serialize_afi_ipv4(self):
342         prefix = '10.0.0.0'
343         peer_ip = '172.16.0.1'
344         body = b'test'  # 4 bytes
345         buf = (
346             b'\x11\x11\x11\x11'  # timestamp
347             b'\x00\x0c\x00\x01'  # type=TYPE_TABLE_DUMP(12),
348                                  # subtype=SUBTYPE_AFI_IPv4(1)
349             b'\x00\x00\x00\x1a'  # length=26
350             b'\x22\x22\x33\x33'  # view_num, seq_num
351             + addrconv.ipv4.text_to_bin(prefix) +  # prefix
352             b'\x18\x01'          # prefix_len=24, status=1
353             b'\x44\x44\x44\x44'  # originated_time
354             + addrconv.ipv4.text_to_bin(peer_ip) +  # peer_ip
355             b'\xfd\xe8\x00\x04'  # peer_as=65000, attr_len=len(body)
356             + body               # bgp_attributes
357         )
358
359         mock_bgp_attr = mock.MagicMock(spec=bgp._PathAttribute)
360         mock_bgp_attr.serialize.return_value = body
361
362         message = mrtlib.TableDumpAfiIPv4MrtMessage(
363             view_num=0x2222,
364             seq_num=0x3333,
365             prefix=prefix,
366             prefix_len=24,
367             status=1,
368             originated_time=0x44444444,
369             peer_ip=peer_ip,
370             peer_as=65000,
371             bgp_attributes=[mock_bgp_attr],
372             # attr_len=4
373         )
374         record = mrtlib.TableDumpMrtRecord(
375             message=message,
376             timestamp=0x11111111,
377             # type_=None,
378             # subtype=None,
379             # length=None,
380         )
381
382         output = record.serialize()
383
384         eq_(buf, output)
385
386     @mock.patch('ryu.lib.packet.bgp._PathAttribute.parser')
387     def test_parse_afi_ipv6(self, mock_bgp_attr_parser):
388         prefix = '2001:db8::1'
389         peer_ip = 'fe80::1'
390         body = b'test'  # 4 bytes
391         buf = (
392             b'\x11\x11\x11\x11'  # timestamp
393             b'\x00\x0c\x00\x02'  # type=TYPE_TABLE_DUMP(12),
394                                  # subtype=SUBTYPE_AFI_IPv6(2)
395             b'\x00\x00\x00\x32'  # length=50
396             b'\x22\x22\x33\x33'  # view_num, seq_num
397             + addrconv.ipv6.text_to_bin(prefix) +  # prefix
398             b'\x40\x01'          # prefix_len=64, status=1
399             b'\x44\x44\x44\x44'  # originated_time
400             + addrconv.ipv6.text_to_bin(peer_ip) +  # peer_ip
401             b'\xfd\xe8\x00\x04'  # peer_as=65000, attr_len=len(body)
402             + body               # bgp_attributes
403         )
404
405         mock_bgp_attr = mock.MagicMock(spec=bgp._PathAttribute)
406         mock_bgp_attr_parser.return_value = (mock_bgp_attr, b'')
407
408         (record, rest) = mrtlib.MrtRecord.parse(buf)
409
410         eq_(0x11111111, record.timestamp)
411         eq_(mrtlib.MrtRecord.TYPE_TABLE_DUMP, record.type)
412         eq_(mrtlib.TableDumpMrtRecord.SUBTYPE_AFI_IPv6, record.subtype)
413         eq_(0x00000032, record.length)
414         eq_(0x2222, record.message.view_num)
415         eq_(0x3333, record.message.seq_num)
416         eq_(prefix, record.message.prefix)
417         eq_(64, record.message.prefix_len)
418         eq_(1, record.message.status)
419         eq_(0x44444444, record.message.originated_time)
420         eq_(peer_ip, record.message.peer_ip)
421         eq_(65000, record.message.peer_as)
422         eq_(0x0004, record.message.attr_len)
423         eq_([mock_bgp_attr], record.message.bgp_attributes)
424         eq_(b'', rest)
425
426     def test_serialize_afi_ipv6(self):
427         prefix = '2001:db8::1'
428         peer_ip = 'fe80::1'
429         body = b'test'  # 4 bytes
430         buf = (
431             b'\x11\x11\x11\x11'  # timestamp
432             b'\x00\x0c\x00\x02'  # type=TYPE_TABLE_DUMP(12),
433                                  # subtype=SUBTYPE_AFI_IPv6(2)
434             b'\x00\x00\x00\x32'  # length=50
435             b'\x22\x22\x33\x33'  # view_num, seq_num
436             + addrconv.ipv6.text_to_bin(prefix) +  # prefix
437             b'\x40\x01'          # prefix_len=64, status=1
438             b'\x44\x44\x44\x44'  # originated_time
439             + addrconv.ipv6.text_to_bin(peer_ip) +  # peer_ip
440             b'\xfd\xe8\x00\x04'  # peer_as=65000, attr_len=len(body)
441             + body               # bgp_attributes
442         )
443
444         mock_bgp_attr = mock.MagicMock(spec=bgp._PathAttribute)
445         mock_bgp_attr.serialize.return_value = body
446
447         message = mrtlib.TableDumpAfiIPv6MrtMessage(
448             view_num=0x2222,
449             seq_num=0x3333,
450             prefix=prefix,
451             prefix_len=64,
452             status=1,
453             originated_time=0x44444444,
454             peer_ip=peer_ip,
455             peer_as=65000,
456             bgp_attributes=[mock_bgp_attr],
457             # attr_len=4
458         )
459         record = mrtlib.TableDumpMrtRecord(
460             message=message,
461             timestamp=0x11111111,
462             # type_=None,
463             # subtype=None,
464             # length=None,
465         )
466
467         output = record.serialize()
468
469         eq_(buf, output)
470
471
472 class TestMrtlibTableDump2MrtRecord(unittest.TestCase):
473     """
474     Test case for ryu.lib.mrtlib.TableDump2MrtRecord.
475     """
476
477     # Note: The classes corresponding to the following subtypes are
478     # tested in TestMrtlibMrtRecord.
479     # - SUBTYPE_PEER_INDEX_TABLE = 1
480     # - SUBTYPE_RIB_IPV4_UNICAST = 2
481     # - SUBTYPE_RIB_IPV4_MULTICAST = 3
482     # - SUBTYPE_RIB_IPV6_UNICAST = 4
483     # - SUBTYPE_RIB_IPV6_MULTICAST = 5
484
485     @mock.patch('ryu.lib.mrtlib.MrtRibEntry.parse')
486     @mock.patch('ryu.lib.packet.bgp.BGPNLRI.parser')
487     def test_parse_rib_generic(self, mock_nlri_parser, mock_rib_entry_parser):
488         nlri_bin = b'nlri'  # 4 bytes
489         rib_entries_bin = b'ribs'  # 4 bytes
490         buf = (
491             b'\x11\x11\x11\x11'  # timestamp
492             b'\x00\x0d\x00\x06'  # type=TYPE_TABLE_DUMP_V2(13),
493                                  # subtype=SUBTYPE_RIB_GENERIC(6)
494             b'\x00\x00\x00\x11'  # length=17
495             b'\x22\x22\x22\x22'  # seq_num
496             b'\x33\x33\x44'      # afi, safi
497             + nlri_bin +         # nlri
498             b'\x00\x01'          # entry_count
499             + rib_entries_bin    # rib_entries
500         )
501         buf_entries = (
502             b'\x00\x01'          # entry_count
503             + rib_entries_bin    # rib_entries
504         )
505
506         mock_bgp_nlri = mock.MagicMock(spec=bgp._AddrPrefix)
507         mock_nlri_parser.return_value = (mock_bgp_nlri, buf_entries)
508
509         mock_rib_entry = mock.MagicMock(spec=mrtlib.MrtRibEntry)
510         mock_rib_entry_parser.return_value = (mock_rib_entry, b'')
511
512         (record, rest) = mrtlib.MrtRecord.parse(buf)
513
514         eq_(0x11111111, record.timestamp)
515         eq_(mrtlib.MrtRecord.TYPE_TABLE_DUMP_V2, record.type)
516         eq_(mrtlib.TableDump2MrtRecord.SUBTYPE_RIB_GENERIC, record.subtype)
517         eq_(0x00000011, record.length)
518         eq_(0x22222222, record.message.seq_num)
519         eq_(0x3333, record.message.afi)
520         eq_(0x44, record.message.safi)
521         eq_(mock_bgp_nlri, record.message.nlri)
522         eq_(0x0001, record.message.entry_count)
523         eq_([mock_rib_entry], record.message.rib_entries)
524         eq_(b'', rest)
525
526     def test_serialize_rib_generic(self):
527         nlri_bin = b'nlri'  # 4 bytes
528         rib_entries_bin = b'ribs'  # 4 bytes
529         buf = (
530             b'\x11\x11\x11\x11'  # timestamp
531             b'\x00\x0d\x00\x06'  # type=TYPE_TABLE_DUMP_V2(13),
532                                  # subtype=SUBTYPE_RIB_GENERIC(6)
533             b'\x00\x00\x00\x11'  # length=17
534             b'\x22\x22\x22\x22'  # seq_num
535             b'\x33\x33\x44'      # afi, safi
536             + nlri_bin +         # nlri
537             b'\x00\x01'          # entry_count
538             + rib_entries_bin    # rib_entries
539         )
540
541         mock_bgp_nlri = mock.MagicMock(spec=bgp._AddrPrefix)
542         mock_bgp_nlri.serialize.return_value = nlri_bin
543
544         mock_rib_entry = mock.MagicMock(spec=mrtlib.MrtRibEntry)
545         mock_rib_entry.serialize.return_value = rib_entries_bin
546
547         message = mrtlib.TableDump2RibGenericMrtMessage(
548             seq_num=0x22222222,
549             afi=0x3333,
550             safi=0x44,
551             nlri=mock_bgp_nlri,
552             rib_entries=[mock_rib_entry],
553             # entry_count=1,
554         )
555         record = mrtlib.TableDump2MrtRecord(
556             message=message,
557             timestamp=0x11111111,
558             # type_=None,
559             # subtype=None,
560             # length=None,
561         )
562
563         output = record.serialize()
564
565         eq_(buf, output)
566
567
568 class TestMrtlibMrtPeer(unittest.TestCase):
569     """
570     Test case for ryu.lib.mrtlib.MrtPeer.
571     """
572
573     def test_parse_two_octet_as(self):
574         bgp_id = '1.1.1.1'
575         ip_addr = '10.0.0.1'
576         buf = (
577             b'\x00'      # type
578             + addrconv.ipv4.text_to_bin(bgp_id)     # bgp_id
579             + addrconv.ipv4.text_to_bin(ip_addr) +  # ip_addr
580             b'\xfd\xe8'  # as_num
581         )
582
583         peer, rest = mrtlib.MrtPeer.parse(buf)
584
585         eq_(0, peer.type)
586         eq_(bgp_id, peer.bgp_id)
587         eq_(ip_addr, peer.ip_addr)
588         eq_(65000, peer.as_num)
589         eq_(b'', rest)
590
591     def test_serialize_two_octet_as(self):
592         bgp_id = '1.1.1.1'
593         ip_addr = '10.0.0.1'
594         buf = (
595             b'\x00'      # type
596             + addrconv.ipv4.text_to_bin(bgp_id)     # bgp_id
597             + addrconv.ipv4.text_to_bin(ip_addr) +  # ip_addr
598             b'\xfd\xe8'  # as_num
599         )
600
601         peer = mrtlib.MrtPeer(
602             bgp_id=bgp_id,
603             ip_addr=ip_addr,
604             as_num=65000,
605             # type_=0,
606         )
607
608         output = peer.serialize()
609
610         eq_(buf, output)
611
612
613 class TestMrtlibMrtRibEntry(unittest.TestCase):
614     """
615     Test case for ryu.lib.mrtlib.MrtRibEntry.
616     """
617
618     def test_parse_add_path(self):
619         peer_index = 1
620         originated_time = 2
621         nexthop = '1.1.1.1'
622         bgp_attribute = bgp.BGPPathAttributeNextHop(nexthop)
623         path_id = 3
624         bgp_attr_buf = bgp_attribute.serialize()
625         attr_len = len(bgp_attr_buf)
626         buf = (
627             b'\x00\x01'  # peer_index
628             b'\x00\x00\x00\x02'  # originated_time
629             b'\x00\x00\x00\x03'  # path_id
630             + struct.pack('!H', attr_len)  # attr_len
631             + bgp_attribute.serialize()    # bgp_attributes
632         )
633
634         rib, rest = mrtlib.MrtRibEntry.parse(buf, is_addpath=True)
635
636         eq_(peer_index, rib.peer_index)
637         eq_(originated_time, rib.originated_time)
638         eq_(path_id, rib.path_id)
639         eq_(attr_len, rib.attr_len)
640         eq_(1, len(rib.bgp_attributes))
641         eq_(nexthop, rib.bgp_attributes[0].value)
642         eq_(b'', rest)
643
644     def test_serialize_add_path(self):
645         peer_index = 1
646         originated_time = 2
647         nexthop = '1.1.1.1'
648         bgp_attribute = bgp.BGPPathAttributeNextHop(nexthop)
649         path_id = 3
650         bgp_attr_buf = bgp_attribute.serialize()
651         attr_len = len(bgp_attr_buf)
652         buf = (
653             b'\x00\x01'  # peer_index
654             b'\x00\x00\x00\x02'  # originated_time
655             b'\x00\x00\x00\x03'  # path_id
656             + struct.pack('!H', attr_len)  # attr_len
657             + bgp_attribute.serialize()    # bgp_attributes
658         )
659
660         rib = mrtlib.MrtRibEntry(
661             peer_index=peer_index,
662             originated_time=originated_time,
663             bgp_attributes=[bgp_attribute],
664             # attr_len=attr_len,
665             path_id=path_id,
666         )
667
668         output = rib.serialize()
669
670         eq_(buf, output)
671
672
673 class TestMrtlibBgp4MpMrtRecord(unittest.TestCase):
674     """
675     Test case for ryu.lib.mrtlib.Bgp4MpMrtRecord.
676     """
677
678     # Note: The classes corresponding to the following subtypes are
679     # tested in TestMrtlibMrtRecord.
680     # - SUBTYPE_BGP4MP_MESSAGE = 1
681     # - SUBTYPE_BGP4MP_MESSAGE_AS4 = 4
682     # - SUBTYPE_BGP4MP_STATE_CHANGE_AS4 = 5
683     # - SUBTYPE_BGP4MP_MESSAGE_LOCAL = 6
684     # - SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL = 7
685
686     def test_parse_state_change_afi_ipv4(self):
687         peer_ip = '10.0.0.1'
688         local_ip = '10.0.0.2'
689         buf = (
690             b'\x11\x11\x11\x11'  # timestamp
691             b'\x00\x10\x00\x00'  # type=TYPE_BGP4MP(16),
692                                  # subtype=SUBTYPE_BGP4MP_STATE_CHANGE(0)
693             b'\x00\x00\x00\x14'  # length=20
694             b'\xfd\xe9\xfd\xea'  # peer_as=65001, local_as=65002
695             b'\x22\x22\x00\x01'  # if_index, addr_family=AFI_IPv4(1)
696             + addrconv.ipv4.text_to_bin(peer_ip)     # peer_ip
697             + addrconv.ipv4.text_to_bin(local_ip) +  # local_ip
698             b'\x00\x01\x00\x02'  # old_state=STATE_IDLE(1),
699                                  # new_state=STATE_CONNECT(2)
700         )
701
702         (record, rest) = mrtlib.MrtRecord.parse(buf)
703
704         eq_(0x11111111, record.timestamp)
705         eq_(mrtlib.MrtRecord.TYPE_BGP4MP, record.type)
706         eq_(mrtlib.Bgp4MpMrtRecord.SUBTYPE_BGP4MP_STATE_CHANGE, record.subtype)
707         eq_(0x00000014, record.length)
708         eq_(65001, record.message.peer_as)
709         eq_(65002, record.message.local_as)
710         eq_(0x2222, record.message.if_index)
711         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.AFI_IPv4,
712             record.message.afi)
713         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.STATE_IDLE,
714             record.message.old_state)
715         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.STATE_CONNECT,
716             record.message.new_state)
717         eq_(b'', rest)
718
719     def test_serialize_state_change_afi_ipv4(self):
720         peer_ip = '10.0.0.1'
721         local_ip = '10.0.0.2'
722         buf = (
723             b'\x11\x11\x11\x11'  # timestamp
724             b'\x00\x10\x00\x00'  # type=TYPE_BGP4MP(16),
725                                  # subtype=SUBTYPE_BGP4MP_STATE_CHANGE(0)
726             b'\x00\x00\x00\x14'  # length=20
727             b'\xfd\xe9\xfd\xea'  # peer_as=65001, local_as=65002
728             b'\x22\x22\x00\x01'  # if_index, addr_family=AFI_IPv4(1)
729             + addrconv.ipv4.text_to_bin(peer_ip)     # peer_ip
730             + addrconv.ipv4.text_to_bin(local_ip) +  # local_ip
731             b'\x00\x01\x00\x02'  # old_state=STATE_IDLE(1),
732                                  # new_state=STATE_CONNECT(2)
733         )
734
735         message = mrtlib.Bgp4MpStateChangeMrtMessage(
736             peer_as=65001,
737             local_as=65002,
738             if_index=0x2222,
739             peer_ip=peer_ip,
740             local_ip=local_ip,
741             old_state=mrtlib.Bgp4MpStateChangeMrtMessage.STATE_IDLE,
742             new_state=mrtlib.Bgp4MpStateChangeMrtMessage.STATE_CONNECT,
743             # afi=mrtlib.Bgp4MpStateChangeMrtMessage.AFI_IPv4,
744         )
745         record = mrtlib.Bgp4MpMrtRecord(
746             message=message,
747             timestamp=0x11111111,
748             # type_=None,
749             # subtype=None,
750             # length=None,
751         )
752
753         output = record.serialize()
754
755         eq_(buf, output)
756
757     def test_parse_state_change_afi_ipv6(self):
758         peer_ip = 'fe80::1'
759         local_ip = 'fe80::2'
760         buf = (
761             b'\x11\x11\x11\x11'  # timestamp
762             b'\x00\x10\x00\x00'  # type=TYPE_BGP4MP(16),
763                                  # subtype=SUBTYPE_BGP4MP_STATE_CHANGE(0)
764             b'\x00\x00\x00\x2c'  # length=44
765             b'\xfd\xe9\xfd\xea'  # peer_as=65001, local_as=65002
766             b'\x22\x22\x00\x02'  # if_index, addr_family=AFI_IPv6(2)
767             + addrconv.ipv6.text_to_bin(peer_ip)     # peer_ip
768             + addrconv.ipv6.text_to_bin(local_ip) +  # local_ip
769             b'\x00\x01\x00\x02'  # old_state=STATE_IDLE(1),
770                                  # new_state=STATE_CONNECT(2)
771         )
772
773         (record, rest) = mrtlib.MrtRecord.parse(buf)
774
775         eq_(0x11111111, record.timestamp)
776         eq_(mrtlib.MrtRecord.TYPE_BGP4MP, record.type)
777         eq_(mrtlib.Bgp4MpMrtRecord.SUBTYPE_BGP4MP_STATE_CHANGE, record.subtype)
778         eq_(0x0000002c, record.length)
779         eq_(65001, record.message.peer_as)
780         eq_(65002, record.message.local_as)
781         eq_(0x2222, record.message.if_index)
782         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.AFI_IPv6,
783             record.message.afi)
784         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.STATE_IDLE,
785             record.message.old_state)
786         eq_(mrtlib.Bgp4MpStateChangeMrtMessage.STATE_CONNECT,
787             record.message.new_state)
788         eq_(b'', rest)
789
790     def test_serialize_state_change_afi_ipv6(self):
791         peer_ip = 'fe80::1'
792         local_ip = 'fe80::2'
793         buf = (
794             b'\x11\x11\x11\x11'  # timestamp
795             b'\x00\x10\x00\x00'  # type=TYPE_BGP4MP(16),
796                                  # subtype=SUBTYPE_BGP4MP_STATE_CHANGE(0)
797             b'\x00\x00\x00\x2c'  # length=44
798             b'\xfd\xe9\xfd\xea'  # peer_as=65001, local_as=65002
799             b'\x22\x22\x00\x02'  # if_index, addr_family=AFI_IPv6(2)
800             + addrconv.ipv6.text_to_bin(peer_ip)     # peer_ip
801             + addrconv.ipv6.text_to_bin(local_ip) +  # local_ip
802             b'\x00\x01\x00\x02'  # old_state=STATE_IDLE(1),
803                                  # new_state=STATE_CONNECT(2)
804         )
805
806         message = mrtlib.Bgp4MpStateChangeMrtMessage(
807             peer_as=65001,
808             local_as=65002,
809             if_index=0x2222,
810             peer_ip=peer_ip,
811             local_ip=local_ip,
812             old_state=mrtlib.Bgp4MpStateChangeMrtMessage.STATE_IDLE,
813             new_state=mrtlib.Bgp4MpStateChangeMrtMessage.STATE_CONNECT,
814             # afi=mrtlib.Bgp4MpStateChangeMrtMessage.AFI_IPv4,
815         )
816         record = mrtlib.Bgp4MpMrtRecord(
817             message=message,
818             timestamp=0x11111111,
819             # type_=None,
820             # subtype=None,
821             # length=None,
822         )
823
824         output = record.serialize()
825
826         eq_(buf, output)