backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / unit / packet / test_bgp.py
1 # Copyright (C) 2013,2014 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013,2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 from __future__ import print_function
18
19 import logging
20 import os
21 import sys
22
23 import unittest
24 from nose.tools import eq_
25 from nose.tools import ok_
26
27 from ryu.utils import binary_str
28 from ryu.lib import pcaplib
29 from ryu.lib.packet import packet
30 from ryu.lib.packet import bgp
31 from ryu.lib.packet import afi
32 from ryu.lib.packet import safi
33
34
35 LOG = logging.getLogger(__name__)
36
37 BGP4_PACKET_DATA_DIR = os.path.join(
38     os.path.dirname(sys.modules[__name__].__file__), '../../packet_data/bgp4/')
39
40 PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT = (
41     bgp.BGPPathAttributePmsiTunnel.TYPE_NO_TUNNEL_INFORMATION_PRESENT
42 )
43 PMSI_TYPE_INGRESS_REPLICATION = (
44     bgp.BGPPathAttributePmsiTunnel.TYPE_INGRESS_REPLICATION
45 )
46
47 RULES_BASE = [
48     # port='>=8000'
49     bgp.FlowSpecPort(
50         operator=(bgp.FlowSpecPort.GT | bgp.FlowSpecPort.EQ),
51         value=8000),
52     # port='&<=9000'
53     bgp.FlowSpecPort(
54         operator=(bgp.FlowSpecPort.AND | bgp.FlowSpecPort.LT |
55                   bgp.FlowSpecPort.EQ),
56         value=9000),
57     # port='==80'
58     bgp.FlowSpecPort(operator=bgp.FlowSpecPort.EQ, value=80),
59     # dst_port=8080
60     bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.EQ, value=8080),
61     # dst_port='>9000'
62     bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.GT, value=9000),
63     # dst_port='&<9050'
64     bgp.FlowSpecDestPort(
65         operator=(bgp.FlowSpecDestPort.AND | bgp.FlowSpecDestPort.LT),
66         value=9050),
67     # dst_port='<=1000'
68     bgp.FlowSpecDestPort(
69         operator=(bgp.FlowSpecDestPort.LT | bgp.FlowSpecDestPort.EQ),
70         value=1000),
71     # src_port='<=9090'
72     bgp.FlowSpecSrcPort(
73         operator=(bgp.FlowSpecSrcPort.LT | bgp.FlowSpecSrcPort.EQ),
74         value=9090),
75     # src_port='& >=9080'
76     bgp.FlowSpecSrcPort(
77         operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT |
78                   bgp.FlowSpecSrcPort.EQ),
79         value=9080),
80     # src_port='<10100'
81     bgp.FlowSpecSrcPort(
82         operator=bgp.FlowSpecSrcPort.LT, value=10100),
83     # src_port='>10000'
84     bgp.FlowSpecSrcPort(
85         operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT),
86         value=10000),
87     # icmp_type=0
88     bgp.FlowSpecIcmpType(operator=bgp.FlowSpecIcmpType.EQ, value=0),
89     # icmp_code=6
90     bgp.FlowSpecIcmpCode(operator=bgp.FlowSpecIcmpCode.EQ, value=6),
91     # tcp_flags='ACK+FIN'
92     bgp.FlowSpecTCPFlags(
93         operator=0,  # Partial match
94         value=(bgp.FlowSpecTCPFlags.SYN | bgp.FlowSpecTCPFlags.ACK)),
95     # tcp_flags='&!=URGENT'
96     bgp.FlowSpecTCPFlags(
97         operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecTCPFlags.NOT),
98         value=bgp.FlowSpecTCPFlags.URGENT),
99     # packet_len=1000
100     bgp.FlowSpecPacketLen(
101         operator=bgp.FlowSpecPacketLen.EQ, value=1000),
102     # packet_len=1100
103     bgp.FlowSpecPacketLen(
104         operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecPacketLen.EQ),
105         value=1100),
106     # dscp=22
107     bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=22),
108     # dscp=24
109     bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=24),
110 ]
111
112 RULES_L2VPN_BASE = [
113     # ether_type=0x0800
114     bgp.FlowSpecEtherType(operator=bgp.FlowSpecEtherType.EQ, value=0x0800),
115     # source_mac='12:34:56:78:90:AB'
116     bgp.FlowSpecSourceMac(addr='12:34:56:78:90:AB', length=6),
117     # dest_mac='DE:EF:C0:FF:EE:DD'
118     bgp.FlowSpecDestinationMac(addr='BE:EF:C0:FF:EE:DD', length=6),
119     # llc_dsap=0x42
120     bgp.FlowSpecLLCDSAP(operator=bgp.FlowSpecLLCDSAP.EQ, value=0x42),
121     # llc_ssap=0x42
122     bgp.FlowSpecLLCSSAP(operator=bgp.FlowSpecLLCSSAP.EQ, value=0x42),
123     # llc_control=100
124     bgp.FlowSpecLLCControl(operator=bgp.FlowSpecLLCControl.EQ, value=100),
125     # snap=0x12345
126     bgp.FlowSpecSNAP(operator=bgp.FlowSpecSNAP.EQ, value=0x12345),
127     # vlan_id='>4000'
128     bgp.FlowSpecVLANID(operator=bgp.FlowSpecVLANID.GT, value=4000),
129     # vlan_cos='>=3'
130     bgp.FlowSpecVLANCoS(
131         operator=(bgp.FlowSpecVLANCoS.GT | bgp.FlowSpecVLANCoS.EQ), value=3),
132     # inner_vlan_id='<3000'
133     bgp.FlowSpecInnerVLANID(operator=bgp.FlowSpecInnerVLANID.LT, value=3000),
134     # inner_vlan_cos='<=5'
135     bgp.FlowSpecInnerVLANCoS(
136         operator=(bgp.FlowSpecInnerVLANCoS.LT | bgp.FlowSpecInnerVLANCoS.EQ),
137         value=5),
138 ]
139
140
141 class Test_bgp(unittest.TestCase):
142     """ Test case for ryu.lib.packet.bgp
143     """
144
145     def setUp(self):
146         pass
147
148     def tearDown(self):
149         pass
150
151     def test_open1(self):
152         msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.1')
153         binmsg = msg.serialize()
154         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
155         eq_(str(msg), str(msg2))
156         eq_(len(msg), 29)
157         eq_(rest, b'')
158
159     def test_open2(self):
160         opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
161                                                       cap_value=b'hoge'),
162                      bgp.BGPOptParamCapabilityGracefulRestart(flags=0,
163                                                               time=120,
164                                                               tuples=[]),
165                      bgp.BGPOptParamCapabilityRouteRefresh(),
166                      bgp.BGPOptParamCapabilityCiscoRouteRefresh(),
167                      bgp.BGPOptParamCapabilityMultiprotocol(
168                          afi=afi.IP, safi=safi.MPLS_VPN),
169                      bgp.BGPOptParamCapabilityCarryingLabelInfo(),
170                      bgp.BGPOptParamCapabilityFourOctetAsNumber(
171                          as_number=1234567),
172                      bgp.BGPOptParamUnknown(type_=99, value=b'fuga')]
173         msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
174                           opt_param=opt_param)
175         binmsg = msg.serialize()
176         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
177         eq_(str(msg), str(msg2))
178         ok_(len(msg) > 29)
179         eq_(rest, b'')
180
181     def test_update1(self):
182         msg = bgp.BGPUpdate()
183         binmsg = msg.serialize()
184         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
185         eq_(str(msg), str(msg2))
186         eq_(len(msg), 23)
187         eq_(rest, b'')
188
189     def test_update2(self):
190         withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0,
191                                                   addr='192.0.2.13'),
192                             bgp.BGPWithdrawnRoute(length=1,
193                                                   addr='192.0.2.13'),
194                             bgp.BGPWithdrawnRoute(length=3,
195                                                   addr='192.0.2.13'),
196                             bgp.BGPWithdrawnRoute(length=7,
197                                                   addr='192.0.2.13'),
198                             bgp.BGPWithdrawnRoute(length=32,
199                                                   addr='192.0.2.13')]
200         mp_nlri = [
201             bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
202                                         route_dist='100:100',
203                                         labels=[1, 2, 3]),
204             bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
205                                         route_dist='10.0.0.1:10000',
206                                         labels=[5, 6, 7, 8]),
207         ]
208         mp_nlri2 = [
209             bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3])
210         ]
211         mp_nlri_v6 = [
212             bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::',
213                                          route_dist='200:200',
214                                          labels=[1, 2, 3]),
215             bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::',
216                                          route_dist='10.0.0.1:10000',
217                                          labels=[5, 6, 7, 8]),
218         ]
219         mp_nlri2_v6 = [
220             bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3])
221         ]
222         communities = [
223             bgp.BGP_COMMUNITY_NO_EXPORT,
224             bgp.BGP_COMMUNITY_NO_ADVERTISE,
225         ]
226         ecommunities = [
227             bgp.BGPTwoOctetAsSpecificExtendedCommunity(
228                 subtype=1, as_number=65500, local_administrator=3908876543),
229             bgp.BGPFourOctetAsSpecificExtendedCommunity(
230                 subtype=2, as_number=10000000, local_administrator=59876),
231             bgp.BGPIPv4AddressSpecificExtendedCommunity(
232                 subtype=3, ipv4_address='192.0.2.1',
233                 local_administrator=65432),
234             bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'),
235             bgp.BGPEncapsulationExtendedCommunity(
236                 subtype=0x0c, tunnel_type=10),
237             bgp.BGPEvpnMacMobilityExtendedCommunity(
238                 subtype=0, flags=0xff, sequence_number=0x11223344),
239             bgp.BGPEvpnEsiLabelExtendedCommunity(
240                 subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'),
241             bgp.BGPEvpnEsiLabelExtendedCommunity(
242                 subtype=1, flags=0xff, mpls_label=0xfffff),
243             bgp.BGPEvpnEsiLabelExtendedCommunity(
244                 subtype=1, flags=0xff, vni=0xffffff),
245             bgp.BGPEvpnEsImportRTExtendedCommunity(
246                 subtype=2, es_import="aa:bb:cc:dd:ee:ff"),
247             bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'),
248         ]
249         path_attributes = [
250             bgp.BGPPathAttributeOrigin(value=1),
251             bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002},
252                                               [1003, 1004]]),
253             bgp.BGPPathAttributeNextHop(value='192.0.2.199'),
254             bgp.BGPPathAttributeMultiExitDisc(value=2000000000),
255             bgp.BGPPathAttributeLocalPref(value=1000000000),
256             bgp.BGPPathAttributeAtomicAggregate(),
257             bgp.BGPPathAttributeAggregator(as_number=40000,
258                                            addr='192.0.2.99'),
259             bgp.BGPPathAttributeCommunities(communities=communities),
260             bgp.BGPPathAttributeOriginatorId(value='10.1.1.1'),
261             bgp.BGPPathAttributeClusterList(value=['1.1.1.1', '2.2.2.2']),
262             bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities),
263             bgp.BGPPathAttributePmsiTunnel(
264                 pmsi_flags=1,
265                 tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
266                 label=b'\xFF\xFF\xFF'),
267             bgp.BGPPathAttributePmsiTunnel(
268                 pmsi_flags=1,
269                 tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
270                 tunnel_id=None),
271             bgp.BGPPathAttributePmsiTunnel(
272                 pmsi_flags=1,
273                 tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
274                 mpls_label=0xfffff,
275                 tunnel_id=bgp.PmsiTunnelIdIngressReplication(
276                     tunnel_endpoint_ip="1.1.1.1")),
277             bgp.BGPPathAttributePmsiTunnel(
278                 pmsi_flags=1,
279                 tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
280                 vni=0xffffff,
281                 tunnel_id=bgp.PmsiTunnelIdIngressReplication(
282                     tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")),
283             bgp.BGPPathAttributePmsiTunnel(
284                 pmsi_flags=1,
285                 tunnel_type=2,
286                 label=b'\xFF\xFF\xFF',
287                 tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')),
288             bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002},
289                                                [1003, 1000004]]),
290             bgp.BGPPathAttributeAs4Aggregator(as_number=100040000,
291                                               addr='192.0.2.99'),
292             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
293                                             next_hop='1.1.1.1',
294                                             nlri=mp_nlri),
295             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL,
296                                             next_hop='1.1.1.1',
297                                             nlri=mp_nlri2),
298             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN,
299                                             next_hop=['2001:db8::1'],
300                                             nlri=mp_nlri_v6),
301             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL,
302                                             next_hop=['2001:db8::1',
303                                                       'fe80::1'],
304                                             nlri=mp_nlri2_v6),
305             bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
306                                               withdrawn_routes=mp_nlri),
307             bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar')
308         ]
309         nlri = [
310             bgp.BGPNLRI(length=24, addr='203.0.113.1'),
311             bgp.BGPNLRI(length=16, addr='203.0.113.0')
312         ]
313         msg = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes,
314                             path_attributes=path_attributes,
315                             nlri=nlri)
316         binmsg = msg.serialize()
317         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
318         eq_(str(msg), str(msg2))
319         ok_(len(msg) > 23)
320         eq_(rest, b'')
321
322     def test_keepalive(self):
323         msg = bgp.BGPKeepAlive()
324         binmsg = msg.serialize()
325         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
326         eq_(str(msg), str(msg2))
327         eq_(len(msg), 19)
328         eq_(rest, b'')
329
330     def test_notification(self):
331         data = b'hoge'
332         msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data)
333         binmsg = msg.serialize()
334         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
335         eq_(str(msg), str(msg2))
336         eq_(len(msg), 21 + len(data))
337         eq_(rest, b'')
338
339     def test_route_refresh(self):
340         msg = bgp.BGPRouteRefresh(afi=afi.IP, safi=safi.MPLS_VPN)
341         binmsg = msg.serialize()
342         msg2, _, rest = bgp.BGPMessage.parser(binmsg)
343         eq_(str(msg), str(msg2))
344         eq_(len(msg), 23)
345         eq_(rest, b'')
346
347     def test_stream_parser(self):
348         msgs = [
349             bgp.BGPNotification(error_code=1, error_subcode=2, data=b'foo'),
350             bgp.BGPNotification(error_code=3, error_subcode=4, data=b'bar'),
351             bgp.BGPNotification(error_code=5, error_subcode=6, data=b'baz'),
352         ]
353         binmsgs = b''.join([bytes(msg.serialize()) for msg in msgs])
354         sp = bgp.StreamParser()
355         results = []
356         for b in binmsgs:
357             for m in sp.parse(b):
358                 results.append(m)
359         eq_(str(results), str(msgs))
360
361     def test_parser(self):
362         files = [
363             'bgp4-open',
364             'bgp4-update',
365             'bgp4-update_ipv6',
366             'bgp4-update_vpnv6',
367             'bgp4-keepalive',
368             'evpn_esi_arbitrary',
369             'evpn_esi_lacp',
370             'evpn_esi_l2_bridge',
371             'evpn_esi_mac_base',
372             'evpn_esi_router_id',
373             'evpn_esi_as_based',
374             'evpn_nlri_eth_a-d',
375             'evpn_nlri_mac_ip_ad',
376             'evpn_nlri_inc_multi_eth_tag',
377             'evpn_nlri_eth_seg',
378             'evpn_nlri_ip_prefix',
379             'flowspec_nlri_ipv4',
380             'flowspec_nlri_vpn4',
381             'flowspec_nlri_ipv6',
382             'flowspec_nlri_vpn6',
383             'flowspec_nlri_l2vpn',
384             'flowspec_action_traffic_rate',
385             'flowspec_action_traffic_action',
386             'flowspec_action_redirect',
387             'flowspec_action_traffic_marking',
388         ]
389
390         for f in files:
391             LOG.debug('*** testing %s ...', f)
392             for _, buf in pcaplib.Reader(
393                     open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb')):
394                 # Checks if BGP message can be parsed as expected.
395                 pkt = packet.Packet(buf)
396                 ok_(isinstance(pkt.protocols[-1], bgp.BGPMessage),
397                     'Failed to parse BGP message: %s' % pkt)
398
399                 # Checks if BGP message can be serialized as expected.
400                 pkt.serialize()
401                 eq_(buf, pkt.data,
402                     "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data)))
403
404     def test_vlan_action_parser(self):
405         action = bgp.BGPFlowSpecVlanActionCommunity(
406             actions_1=(bgp.BGPFlowSpecVlanActionCommunity.POP |
407                        bgp.BGPFlowSpecVlanActionCommunity.SWAP),
408             vlan_1=3000,
409             cos_1=3,
410             actions_2=bgp.BGPFlowSpecVlanActionCommunity.PUSH,
411             vlan_2=4000,
412             cos_2=2,
413         )
414         binmsg = action.serialize()
415         msg, rest = bgp.BGPFlowSpecVlanActionCommunity.parse(binmsg)
416         eq_(str(action), str(msg))
417         eq_(rest, b'')
418
419     def test_tpid_action_parser(self):
420         action = bgp.BGPFlowSpecTPIDActionCommunity(
421             actions=(bgp.BGPFlowSpecTPIDActionCommunity.TI |
422                      bgp.BGPFlowSpecTPIDActionCommunity.TO),
423             tpid_1=5,
424             tpid_2=6,
425         )
426         binmsg = action.serialize()
427         msg, rest = bgp.BGPFlowSpecTPIDActionCommunity.parse(binmsg)
428         eq_(str(action), str(msg))
429         eq_(rest, b'')
430
431     def test_json1(self):
432         opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200,
433                                                       cap_value=b'hoge'),
434                      bgp.BGPOptParamCapabilityRouteRefresh(),
435                      bgp.BGPOptParamCapabilityMultiprotocol(
436                          afi=afi.IP, safi=safi.MPLS_VPN),
437                      bgp.BGPOptParamCapabilityFourOctetAsNumber(
438                          as_number=1234567),
439                      bgp.BGPOptParamUnknown(type_=99, value=b'fuga')]
440         msg1 = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2',
441                            opt_param=opt_param)
442         jsondict = msg1.to_jsondict()
443         msg2 = bgp.BGPOpen.from_jsondict(jsondict['BGPOpen'])
444         eq_(str(msg1), str(msg2))
445
446     def test_json2(self):
447         withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0,
448                                                   addr='192.0.2.13'),
449                             bgp.BGPWithdrawnRoute(length=1,
450                                                   addr='192.0.2.13'),
451                             bgp.BGPWithdrawnRoute(length=3,
452                                                   addr='192.0.2.13'),
453                             bgp.BGPWithdrawnRoute(length=7,
454                                                   addr='192.0.2.13'),
455                             bgp.BGPWithdrawnRoute(length=32,
456                                                   addr='192.0.2.13')]
457         mp_nlri = [
458             bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0',
459                                         route_dist='100:100',
460                                         labels=[1, 2, 3]),
461             bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192',
462                                         route_dist='10.0.0.1:10000',
463                                         labels=[5, 6, 7, 8]),
464         ]
465         mp_nlri2 = [
466             bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3])
467         ]
468         mp_nlri_v6 = [
469             bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::',
470                                          route_dist='200:200',
471                                          labels=[1, 2, 3]),
472             bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::',
473                                          route_dist='10.0.0.1:10000',
474                                          labels=[5, 6, 7, 8]),
475         ]
476         mp_nlri2_v6 = [
477             bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3])
478         ]
479         communities = [
480             bgp.BGP_COMMUNITY_NO_EXPORT,
481             bgp.BGP_COMMUNITY_NO_ADVERTISE,
482         ]
483         ecommunities = [
484             bgp.BGPTwoOctetAsSpecificExtendedCommunity(
485                 subtype=1, as_number=65500, local_administrator=3908876543),
486             bgp.BGPFourOctetAsSpecificExtendedCommunity(
487                 subtype=2, as_number=10000000, local_administrator=59876),
488             bgp.BGPIPv4AddressSpecificExtendedCommunity(
489                 subtype=3, ipv4_address='192.0.2.1',
490                 local_administrator=65432),
491             bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'),
492             bgp.BGPEncapsulationExtendedCommunity(
493                 subtype=0x0c, tunnel_type=10),
494             bgp.BGPEvpnMacMobilityExtendedCommunity(
495                 subtype=0, flags=0xff, sequence_number=0x11223344),
496             bgp.BGPEvpnEsiLabelExtendedCommunity(
497                 subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'),
498             bgp.BGPEvpnEsiLabelExtendedCommunity(
499                 subtype=1, flags=0xff, mpls_label=0xfffff),
500             bgp.BGPEvpnEsiLabelExtendedCommunity(
501                 subtype=1, flags=0xff, vni=0xffffff),
502             bgp.BGPEvpnEsImportRTExtendedCommunity(
503                 subtype=2, es_import="aa:bb:cc:dd:ee:ff"),
504             bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'),
505         ]
506         path_attributes = [
507             bgp.BGPPathAttributeOrigin(value=1),
508             bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002},
509                                               [1003, 1004]]),
510             bgp.BGPPathAttributeNextHop(value='192.0.2.199'),
511             bgp.BGPPathAttributeMultiExitDisc(value=2000000000),
512             bgp.BGPPathAttributeLocalPref(value=1000000000),
513             bgp.BGPPathAttributeAtomicAggregate(),
514             bgp.BGPPathAttributeAggregator(as_number=40000,
515                                            addr='192.0.2.99'),
516             bgp.BGPPathAttributeCommunities(communities=communities),
517             bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities),
518             bgp.BGPPathAttributePmsiTunnel(
519                 pmsi_flags=1,
520                 tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
521                 label=b'\xFF\xFF\xFF'),
522             bgp.BGPPathAttributePmsiTunnel(
523                 pmsi_flags=1,
524                 tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT,
525                 tunnel_id=None),
526             bgp.BGPPathAttributePmsiTunnel(
527                 pmsi_flags=1,
528                 tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
529                 mpls_label=0xfffff,
530                 tunnel_id=bgp.PmsiTunnelIdIngressReplication(
531                     tunnel_endpoint_ip="1.1.1.1")),
532             bgp.BGPPathAttributePmsiTunnel(
533                 pmsi_flags=1,
534                 tunnel_type=PMSI_TYPE_INGRESS_REPLICATION,
535                 vni=0xffffff,
536                 tunnel_id=bgp.PmsiTunnelIdIngressReplication(
537                     tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")),
538             bgp.BGPPathAttributePmsiTunnel(
539                 pmsi_flags=1,
540                 tunnel_type=2,
541                 label=b'\xFF\xFF\xFF',
542                 tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')),
543             bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002},
544                                                [1003, 1000004]]),
545             bgp.BGPPathAttributeAs4Aggregator(as_number=100040000,
546                                               addr='192.0.2.99'),
547             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
548                                             next_hop='1.1.1.1',
549                                             nlri=mp_nlri),
550             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL,
551                                             next_hop='1.1.1.1',
552                                             nlri=mp_nlri2),
553             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN,
554                                             next_hop=['2001:db8::1'],
555                                             nlri=mp_nlri_v6),
556             bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL,
557                                             next_hop=['2001:db8::1',
558                                                       'fe80::1'],
559                                             nlri=mp_nlri2_v6),
560             bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN,
561                                               withdrawn_routes=mp_nlri),
562             bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar')
563         ]
564         nlri = [
565             bgp.BGPNLRI(length=24, addr='203.0.113.1'),
566             bgp.BGPNLRI(length=16, addr='203.0.113.0')
567         ]
568         msg1 = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes,
569                              path_attributes=path_attributes,
570                              nlri=nlri)
571         jsondict = msg1.to_jsondict()
572         msg2 = bgp.BGPUpdate.from_jsondict(jsondict['BGPUpdate'])
573         eq_(str(msg1), str(msg2))
574
575     def test_flowspec_user_interface_ipv4(self):
576         rules = RULES_BASE + [
577             # dst_prefix='10.0.0.0/24
578             bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24),
579             # src_prefix='20.0.0.1/24'
580             bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24),
581             # ip_proto='6'
582             bgp.FlowSpecIPProtocol(
583                 operator=bgp.FlowSpecIPProtocol.EQ, value=6),
584             # fragment='LF'
585             bgp.FlowSpecFragment(
586                 operator=0,  # Partial match
587                 value=bgp.FlowSpecFragment.LF),
588             # fragment='==FF'
589             bgp.FlowSpecFragment(
590                 operator=bgp.FlowSpecFragment.MATCH,
591                 value=bgp.FlowSpecFragment.FF),
592             # fragment='&==ISF'
593             bgp.FlowSpecFragment(
594                 operator=(bgp.FlowSpecFragment.AND |
595                           bgp.FlowSpecFragment.MATCH),
596                 value=bgp.FlowSpecFragment.ISF),
597             # fragment='!=DF'
598             bgp.FlowSpecFragment(
599                 operator=bgp.FlowSpecFragment.NOT,
600                 value=bgp.FlowSpecFragment.DF)
601         ]
602
603         msg = bgp.FlowSpecIPv4NLRI.from_user(
604             dst_prefix='10.0.0.0/24',
605             src_prefix='20.0.0.0/24',
606             ip_proto='6',
607             port='>=8000 & <=9000 | ==80',
608             dst_port='8080 >9000&<9050 | <=1000',
609             src_port='<=9090 & >=9080 <10100 & >10000',
610             icmp_type=0,
611             icmp_code=6,
612             tcp_flags='SYN+ACK & !=URGENT',
613             packet_len='1000 & 1100',
614             dscp='22 24',
615             fragment='LF ==FF&==ISF | !=DF')
616         msg2 = bgp.FlowSpecIPv4NLRI(rules=rules)
617         binmsg = msg.serialize()
618         binmsg2 = msg2.serialize()
619         eq_(str(msg), str(msg2))
620         eq_(binary_str(binmsg), binary_str(binmsg2))
621         msg3, rest = bgp.FlowSpecIPv4NLRI.parser(binmsg)
622         eq_(str(msg), str(msg3))
623         eq_(rest, b'')
624
625     def test_flowspec_user_interface_vpv4(self):
626         rules = RULES_BASE + [
627             # dst_prefix='10.0.0.0/24
628             bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24),
629             # src_prefix='20.0.0.1/24'
630             bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24),
631             # ip_proto='6'
632             bgp.FlowSpecIPProtocol(
633                 operator=bgp.FlowSpecIPProtocol.EQ, value=6),
634             # fragment='LF'
635             bgp.FlowSpecFragment(
636                 operator=0,  # Partial match
637                 value=bgp.FlowSpecFragment.LF),
638             # fragment='==FF'
639             bgp.FlowSpecFragment(
640                 operator=bgp.FlowSpecFragment.MATCH,
641                 value=bgp.FlowSpecFragment.FF),
642             # fragment='&==ISF'
643             bgp.FlowSpecFragment(
644                 operator=(bgp.FlowSpecFragment.AND |
645                           bgp.FlowSpecFragment.MATCH),
646                 value=bgp.FlowSpecFragment.ISF),
647             # fragment='!=DF'
648             bgp.FlowSpecFragment(
649                 operator=bgp.FlowSpecFragment.NOT,
650                 value=bgp.FlowSpecFragment.DF)
651         ]
652         msg = bgp.FlowSpecVPNv4NLRI.from_user(
653             route_dist='65001:250',
654             dst_prefix='10.0.0.0/24',
655             src_prefix='20.0.0.0/24',
656             ip_proto='6',
657             port='>=8000 & <=9000 | ==80',
658             dst_port='8080 >9000&<9050 | <=1000',
659             src_port='<=9090 & >=9080 <10100 & >10000',
660             icmp_type=0,
661             icmp_code=6,
662             tcp_flags='SYN+ACK & !=URGENT',
663             packet_len='1000 & 1100',
664             dscp='22 24',
665             fragment='LF ==FF&==ISF | !=DF')
666         msg2 = bgp.FlowSpecVPNv4NLRI(route_dist='65001:250', rules=rules)
667         binmsg = msg.serialize()
668         binmsg2 = msg2.serialize()
669         eq_(str(msg), str(msg2))
670         eq_(binary_str(binmsg), binary_str(binmsg2))
671         msg3, rest = bgp.FlowSpecVPNv4NLRI.parser(binmsg)
672         eq_(str(msg), str(msg3))
673         eq_(rest, b'')
674
675     def test_flowspec_user_interface_ipv6(self):
676         rules = RULES_BASE + [
677             # dst_prefix='2001:2/128/32'
678             bgp.FlowSpecIPv6DestPrefix(
679                 addr='2001::2', offset=32, length=128),
680             # src_prefix='3002::3/128'
681             bgp.FlowSpecIPv6SrcPrefix(
682                 addr='3002::3', length=128),
683             # ip_proto='6'
684             bgp.FlowSpecNextHeader(
685                 operator=bgp.FlowSpecNextHeader.EQ, value=6),
686             # fragment='LF'
687             bgp.FlowSpecIPv6Fragment(
688                 operator=0,  # Partial match
689                 value=bgp.FlowSpecFragment.LF),
690             # fragment='==FF'
691             bgp.FlowSpecIPv6Fragment(
692                 operator=bgp.FlowSpecFragment.MATCH,
693                 value=bgp.FlowSpecFragment.FF),
694             # fragment='&==ISF'
695             bgp.FlowSpecIPv6Fragment(
696                 operator=(bgp.FlowSpecFragment.AND |
697                           bgp.FlowSpecFragment.MATCH),
698                 value=bgp.FlowSpecFragment.ISF),
699             # fragment='!=LF'
700             bgp.FlowSpecIPv6Fragment(
701                 operator=bgp.FlowSpecFragment.NOT,
702                 value=bgp.FlowSpecFragment.LF),
703             # flowlabel='100'
704             bgp.FlowSpecIPv6FlowLabel(
705                 operator=bgp.FlowSpecIPv6FlowLabel.EQ,
706                 value=100),
707         ]
708         msg = bgp.FlowSpecIPv6NLRI.from_user(
709             dst_prefix='2001::2/128/32',
710             src_prefix='3002::3/128',
711             next_header='6',
712             port='>=8000 & <=9000 | ==80',
713             dst_port='8080 >9000&<9050 | <=1000',
714             src_port='<=9090 & >=9080 <10100 & >10000',
715             icmp_type=0,
716             icmp_code=6,
717             tcp_flags='SYN+ACK & !=URGENT',
718             packet_len='1000 & 1100',
719             dscp='22 24',
720             fragment='LF ==FF&==ISF | !=LF',
721             flow_label=100,
722         )
723         msg2 = bgp.FlowSpecIPv6NLRI(rules=rules)
724         binmsg = msg.serialize()
725         binmsg2 = msg2.serialize()
726         eq_(str(msg), str(msg2))
727         eq_(binary_str(binmsg), binary_str(binmsg2))
728         msg3, rest = bgp.FlowSpecIPv6NLRI.parser(binmsg)
729         eq_(str(msg), str(msg3))
730         eq_(rest, b'')
731
732     def test_flowspec_user_interface_vpnv6(self):
733         rules = RULES_BASE + [
734             # dst_prefix='2001:2/128/32'
735             bgp.FlowSpecIPv6DestPrefix(
736                 addr='2001::2', offset=32, length=128),
737             # src_prefix='3002::3/128'
738             bgp.FlowSpecIPv6SrcPrefix(
739                 addr='3002::3', length=128),
740             # ip_proto='6'
741             bgp.FlowSpecNextHeader(
742                 operator=bgp.FlowSpecNextHeader.EQ, value=6),
743             # fragment='LF'
744             bgp.FlowSpecIPv6Fragment(
745                 operator=0,  # Partial match
746                 value=bgp.FlowSpecFragment.LF),
747             # fragment='==FF'
748             bgp.FlowSpecIPv6Fragment(
749                 operator=bgp.FlowSpecFragment.MATCH,
750                 value=bgp.FlowSpecFragment.FF),
751             # fragment='&==ISF'
752             bgp.FlowSpecIPv6Fragment(
753                 operator=(bgp.FlowSpecFragment.AND |
754                           bgp.FlowSpecFragment.MATCH),
755                 value=bgp.FlowSpecFragment.ISF),
756             # fragment='!=LF'
757             bgp.FlowSpecIPv6Fragment(
758                 operator=bgp.FlowSpecFragment.NOT,
759                 value=bgp.FlowSpecFragment.LF),
760             # flowlabel='100'
761             bgp.FlowSpecIPv6FlowLabel(
762                 operator=bgp.FlowSpecIPv6FlowLabel.EQ,
763                 value=100),
764         ]
765         msg = bgp.FlowSpecVPNv6NLRI.from_user(
766             route_dist='65001:250',
767             dst_prefix='2001::2/128/32',
768             src_prefix='3002::3/128',
769             next_header='6',
770             port='>=8000 & <=9000 | ==80',
771             dst_port='8080 >9000&<9050 | <=1000',
772             src_port='<=9090 & >=9080 <10100 & >10000',
773             icmp_type=0,
774             icmp_code=6,
775             tcp_flags='SYN+ACK & !=URGENT',
776             packet_len='1000 & 1100',
777             dscp='22 24',
778             fragment='LF ==FF&==ISF | !=LF',
779             flow_label=100,
780         )
781         msg2 = bgp.FlowSpecVPNv6NLRI(route_dist='65001:250', rules=rules)
782         binmsg = msg.serialize()
783         binmsg2 = msg2.serialize()
784         eq_(str(msg), str(msg2))
785         eq_(binary_str(binmsg), binary_str(binmsg2))
786         msg3, rest = bgp.FlowSpecVPNv6NLRI.parser(binmsg)
787         eq_(str(msg), str(msg3))
788         eq_(rest, b'')
789
790     def test_flowspec_user_interface_l2vpn(self):
791         rules = RULES_L2VPN_BASE
792         msg = bgp.FlowSpecL2VPNNLRI.from_user(
793             route_dist='65001:250',
794             ether_type=0x0800,
795             src_mac='12:34:56:78:90:AB',
796             dst_mac='BE:EF:C0:FF:EE:DD',
797             llc_dsap=0x42,
798             llc_ssap=0x42,
799             llc_control=100,
800             snap=0x12345,
801             vlan_id='>4000',
802             vlan_cos='>=3',
803             inner_vlan_id='<3000',
804             inner_vlan_cos='<=5',
805         )
806         msg2 = bgp.FlowSpecL2VPNNLRI(route_dist='65001:250', rules=rules)
807         binmsg = msg.serialize()
808         binmsg2 = msg2.serialize()
809         eq_(str(msg), str(msg2))
810         eq_(binary_str(binmsg), binary_str(binmsg2))
811         msg3, rest = bgp.FlowSpecL2VPNNLRI.parser(binmsg)
812         eq_(str(msg), str(msg3))
813         eq_(rest, b'')