diff options
Diffstat (limited to 'tests/unit/packet/test_bgp.py')
-rw-r--r-- | tests/unit/packet/test_bgp.py | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/tests/unit/packet/test_bgp.py b/tests/unit/packet/test_bgp.py new file mode 100644 index 00000000..2211fc4c --- /dev/null +++ b/tests/unit/packet/test_bgp.py @@ -0,0 +1,813 @@ +# Copyright (C) 2013,2014 Nippon Telegraph and Telephone Corporation. +# Copyright (C) 2013,2014 YAMAMOTO Takashi <yamamoto at valinux co jp> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function + +import logging +import os +import sys + +import unittest +from nose.tools import eq_ +from nose.tools import ok_ + +from ryu.utils import binary_str +from ryu.lib import pcaplib +from ryu.lib.packet import packet +from ryu.lib.packet import bgp +from ryu.lib.packet import afi +from ryu.lib.packet import safi + + +LOG = logging.getLogger(__name__) + +BGP4_PACKET_DATA_DIR = os.path.join( + os.path.dirname(sys.modules[__name__].__file__), '../../packet_data/bgp4/') + +PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT = ( + bgp.BGPPathAttributePmsiTunnel.TYPE_NO_TUNNEL_INFORMATION_PRESENT +) +PMSI_TYPE_INGRESS_REPLICATION = ( + bgp.BGPPathAttributePmsiTunnel.TYPE_INGRESS_REPLICATION +) + +RULES_BASE = [ + # port='>=8000' + bgp.FlowSpecPort( + operator=(bgp.FlowSpecPort.GT | bgp.FlowSpecPort.EQ), + value=8000), + # port='&<=9000' + bgp.FlowSpecPort( + operator=(bgp.FlowSpecPort.AND | bgp.FlowSpecPort.LT | + bgp.FlowSpecPort.EQ), + value=9000), + # port='==80' + bgp.FlowSpecPort(operator=bgp.FlowSpecPort.EQ, value=80), + # dst_port=8080 + bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.EQ, value=8080), + # dst_port='>9000' + bgp.FlowSpecDestPort(operator=bgp.FlowSpecDestPort.GT, value=9000), + # dst_port='&<9050' + bgp.FlowSpecDestPort( + operator=(bgp.FlowSpecDestPort.AND | bgp.FlowSpecDestPort.LT), + value=9050), + # dst_port='<=1000' + bgp.FlowSpecDestPort( + operator=(bgp.FlowSpecDestPort.LT | bgp.FlowSpecDestPort.EQ), + value=1000), + # src_port='<=9090' + bgp.FlowSpecSrcPort( + operator=(bgp.FlowSpecSrcPort.LT | bgp.FlowSpecSrcPort.EQ), + value=9090), + # src_port='& >=9080' + bgp.FlowSpecSrcPort( + operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT | + bgp.FlowSpecSrcPort.EQ), + value=9080), + # src_port='<10100' + bgp.FlowSpecSrcPort( + operator=bgp.FlowSpecSrcPort.LT, value=10100), + # src_port='>10000' + bgp.FlowSpecSrcPort( + operator=(bgp.FlowSpecSrcPort.AND | bgp.FlowSpecSrcPort.GT), + value=10000), + # icmp_type=0 + bgp.FlowSpecIcmpType(operator=bgp.FlowSpecIcmpType.EQ, value=0), + # icmp_code=6 + bgp.FlowSpecIcmpCode(operator=bgp.FlowSpecIcmpCode.EQ, value=6), + # tcp_flags='ACK+FIN' + bgp.FlowSpecTCPFlags( + operator=0, # Partial match + value=(bgp.FlowSpecTCPFlags.SYN | bgp.FlowSpecTCPFlags.ACK)), + # tcp_flags='&!=URGENT' + bgp.FlowSpecTCPFlags( + operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecTCPFlags.NOT), + value=bgp.FlowSpecTCPFlags.URGENT), + # packet_len=1000 + bgp.FlowSpecPacketLen( + operator=bgp.FlowSpecPacketLen.EQ, value=1000), + # packet_len=1100 + bgp.FlowSpecPacketLen( + operator=(bgp.FlowSpecTCPFlags.AND | bgp.FlowSpecPacketLen.EQ), + value=1100), + # dscp=22 + bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=22), + # dscp=24 + bgp.FlowSpecDSCP(operator=bgp.FlowSpecDSCP.EQ, value=24), +] + +RULES_L2VPN_BASE = [ + # ether_type=0x0800 + bgp.FlowSpecEtherType(operator=bgp.FlowSpecEtherType.EQ, value=0x0800), + # source_mac='12:34:56:78:90:AB' + bgp.FlowSpecSourceMac(addr='12:34:56:78:90:AB', length=6), + # dest_mac='DE:EF:C0:FF:EE:DD' + bgp.FlowSpecDestinationMac(addr='BE:EF:C0:FF:EE:DD', length=6), + # llc_dsap=0x42 + bgp.FlowSpecLLCDSAP(operator=bgp.FlowSpecLLCDSAP.EQ, value=0x42), + # llc_ssap=0x42 + bgp.FlowSpecLLCSSAP(operator=bgp.FlowSpecLLCSSAP.EQ, value=0x42), + # llc_control=100 + bgp.FlowSpecLLCControl(operator=bgp.FlowSpecLLCControl.EQ, value=100), + # snap=0x12345 + bgp.FlowSpecSNAP(operator=bgp.FlowSpecSNAP.EQ, value=0x12345), + # vlan_id='>4000' + bgp.FlowSpecVLANID(operator=bgp.FlowSpecVLANID.GT, value=4000), + # vlan_cos='>=3' + bgp.FlowSpecVLANCoS( + operator=(bgp.FlowSpecVLANCoS.GT | bgp.FlowSpecVLANCoS.EQ), value=3), + # inner_vlan_id='<3000' + bgp.FlowSpecInnerVLANID(operator=bgp.FlowSpecInnerVLANID.LT, value=3000), + # inner_vlan_cos='<=5' + bgp.FlowSpecInnerVLANCoS( + operator=(bgp.FlowSpecInnerVLANCoS.LT | bgp.FlowSpecInnerVLANCoS.EQ), + value=5), +] + + +class Test_bgp(unittest.TestCase): + """ Test case for ryu.lib.packet.bgp + """ + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_open1(self): + msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.1') + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + eq_(len(msg), 29) + eq_(rest, b'') + + def test_open2(self): + opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200, + cap_value=b'hoge'), + bgp.BGPOptParamCapabilityGracefulRestart(flags=0, + time=120, + tuples=[]), + bgp.BGPOptParamCapabilityRouteRefresh(), + bgp.BGPOptParamCapabilityCiscoRouteRefresh(), + bgp.BGPOptParamCapabilityMultiprotocol( + afi=afi.IP, safi=safi.MPLS_VPN), + bgp.BGPOptParamCapabilityCarryingLabelInfo(), + bgp.BGPOptParamCapabilityFourOctetAsNumber( + as_number=1234567), + bgp.BGPOptParamUnknown(type_=99, value=b'fuga')] + msg = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2', + opt_param=opt_param) + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + ok_(len(msg) > 29) + eq_(rest, b'') + + def test_update1(self): + msg = bgp.BGPUpdate() + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + eq_(len(msg), 23) + eq_(rest, b'') + + def test_update2(self): + withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=1, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=3, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=7, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=32, + addr='192.0.2.13')] + mp_nlri = [ + bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0', + route_dist='100:100', + labels=[1, 2, 3]), + bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192', + route_dist='10.0.0.1:10000', + labels=[5, 6, 7, 8]), + ] + mp_nlri2 = [ + bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3]) + ] + mp_nlri_v6 = [ + bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::', + route_dist='200:200', + labels=[1, 2, 3]), + bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::', + route_dist='10.0.0.1:10000', + labels=[5, 6, 7, 8]), + ] + mp_nlri2_v6 = [ + bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3]) + ] + communities = [ + bgp.BGP_COMMUNITY_NO_EXPORT, + bgp.BGP_COMMUNITY_NO_ADVERTISE, + ] + ecommunities = [ + bgp.BGPTwoOctetAsSpecificExtendedCommunity( + subtype=1, as_number=65500, local_administrator=3908876543), + bgp.BGPFourOctetAsSpecificExtendedCommunity( + subtype=2, as_number=10000000, local_administrator=59876), + bgp.BGPIPv4AddressSpecificExtendedCommunity( + subtype=3, ipv4_address='192.0.2.1', + local_administrator=65432), + bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'), + bgp.BGPEncapsulationExtendedCommunity( + subtype=0x0c, tunnel_type=10), + bgp.BGPEvpnMacMobilityExtendedCommunity( + subtype=0, flags=0xff, sequence_number=0x11223344), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, mpls_label=0xfffff), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, vni=0xffffff), + bgp.BGPEvpnEsImportRTExtendedCommunity( + subtype=2, es_import="aa:bb:cc:dd:ee:ff"), + bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'), + ] + path_attributes = [ + bgp.BGPPathAttributeOrigin(value=1), + bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002}, + [1003, 1004]]), + bgp.BGPPathAttributeNextHop(value='192.0.2.199'), + bgp.BGPPathAttributeMultiExitDisc(value=2000000000), + bgp.BGPPathAttributeLocalPref(value=1000000000), + bgp.BGPPathAttributeAtomicAggregate(), + bgp.BGPPathAttributeAggregator(as_number=40000, + addr='192.0.2.99'), + bgp.BGPPathAttributeCommunities(communities=communities), + bgp.BGPPathAttributeOriginatorId(value='10.1.1.1'), + bgp.BGPPathAttributeClusterList(value=['1.1.1.1', '2.2.2.2']), + bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT, + label=b'\xFF\xFF\xFF'), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT, + tunnel_id=None), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_INGRESS_REPLICATION, + mpls_label=0xfffff, + tunnel_id=bgp.PmsiTunnelIdIngressReplication( + tunnel_endpoint_ip="1.1.1.1")), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_INGRESS_REPLICATION, + vni=0xffffff, + tunnel_id=bgp.PmsiTunnelIdIngressReplication( + tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=2, + label=b'\xFF\xFF\xFF', + tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')), + bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002}, + [1003, 1000004]]), + bgp.BGPPathAttributeAs4Aggregator(as_number=100040000, + addr='192.0.2.99'), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, + next_hop='1.1.1.1', + nlri=mp_nlri), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL, + next_hop='1.1.1.1', + nlri=mp_nlri2), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN, + next_hop=['2001:db8::1'], + nlri=mp_nlri_v6), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL, + next_hop=['2001:db8::1', + 'fe80::1'], + nlri=mp_nlri2_v6), + bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, + withdrawn_routes=mp_nlri), + bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar') + ] + nlri = [ + bgp.BGPNLRI(length=24, addr='203.0.113.1'), + bgp.BGPNLRI(length=16, addr='203.0.113.0') + ] + msg = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes, + path_attributes=path_attributes, + nlri=nlri) + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + ok_(len(msg) > 23) + eq_(rest, b'') + + def test_keepalive(self): + msg = bgp.BGPKeepAlive() + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + eq_(len(msg), 19) + eq_(rest, b'') + + def test_notification(self): + data = b'hoge' + msg = bgp.BGPNotification(error_code=1, error_subcode=2, data=data) + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + eq_(len(msg), 21 + len(data)) + eq_(rest, b'') + + def test_route_refresh(self): + msg = bgp.BGPRouteRefresh(afi=afi.IP, safi=safi.MPLS_VPN) + binmsg = msg.serialize() + msg2, _, rest = bgp.BGPMessage.parser(binmsg) + eq_(str(msg), str(msg2)) + eq_(len(msg), 23) + eq_(rest, b'') + + def test_stream_parser(self): + msgs = [ + bgp.BGPNotification(error_code=1, error_subcode=2, data=b'foo'), + bgp.BGPNotification(error_code=3, error_subcode=4, data=b'bar'), + bgp.BGPNotification(error_code=5, error_subcode=6, data=b'baz'), + ] + binmsgs = b''.join([bytes(msg.serialize()) for msg in msgs]) + sp = bgp.StreamParser() + results = [] + for b in binmsgs: + for m in sp.parse(b): + results.append(m) + eq_(str(results), str(msgs)) + + def test_parser(self): + files = [ + 'bgp4-open', + 'bgp4-update', + 'bgp4-update_ipv6', + 'bgp4-update_vpnv6', + 'bgp4-keepalive', + 'evpn_esi_arbitrary', + 'evpn_esi_lacp', + 'evpn_esi_l2_bridge', + 'evpn_esi_mac_base', + 'evpn_esi_router_id', + 'evpn_esi_as_based', + 'evpn_nlri_eth_a-d', + 'evpn_nlri_mac_ip_ad', + 'evpn_nlri_inc_multi_eth_tag', + 'evpn_nlri_eth_seg', + 'evpn_nlri_ip_prefix', + 'flowspec_nlri_ipv4', + 'flowspec_nlri_vpn4', + 'flowspec_nlri_ipv6', + 'flowspec_nlri_vpn6', + 'flowspec_nlri_l2vpn', + 'flowspec_action_traffic_rate', + 'flowspec_action_traffic_action', + 'flowspec_action_redirect', + 'flowspec_action_traffic_marking', + ] + + for f in files: + LOG.debug('*** testing %s ...', f) + for _, buf in pcaplib.Reader( + open(BGP4_PACKET_DATA_DIR + f + '.pcap', 'rb')): + # Checks if BGP message can be parsed as expected. + pkt = packet.Packet(buf) + ok_(isinstance(pkt.protocols[-1], bgp.BGPMessage), + 'Failed to parse BGP message: %s' % pkt) + + # Checks if BGP message can be serialized as expected. + pkt.serialize() + eq_(buf, pkt.data, + "b'%s' != b'%s'" % (binary_str(buf), binary_str(pkt.data))) + + def test_vlan_action_parser(self): + action = bgp.BGPFlowSpecVlanActionCommunity( + actions_1=(bgp.BGPFlowSpecVlanActionCommunity.POP | + bgp.BGPFlowSpecVlanActionCommunity.SWAP), + vlan_1=3000, + cos_1=3, + actions_2=bgp.BGPFlowSpecVlanActionCommunity.PUSH, + vlan_2=4000, + cos_2=2, + ) + binmsg = action.serialize() + msg, rest = bgp.BGPFlowSpecVlanActionCommunity.parse(binmsg) + eq_(str(action), str(msg)) + eq_(rest, b'') + + def test_tpid_action_parser(self): + action = bgp.BGPFlowSpecTPIDActionCommunity( + actions=(bgp.BGPFlowSpecTPIDActionCommunity.TI | + bgp.BGPFlowSpecTPIDActionCommunity.TO), + tpid_1=5, + tpid_2=6, + ) + binmsg = action.serialize() + msg, rest = bgp.BGPFlowSpecTPIDActionCommunity.parse(binmsg) + eq_(str(action), str(msg)) + eq_(rest, b'') + + def test_json1(self): + opt_param = [bgp.BGPOptParamCapabilityUnknown(cap_code=200, + cap_value=b'hoge'), + bgp.BGPOptParamCapabilityRouteRefresh(), + bgp.BGPOptParamCapabilityMultiprotocol( + afi=afi.IP, safi=safi.MPLS_VPN), + bgp.BGPOptParamCapabilityFourOctetAsNumber( + as_number=1234567), + bgp.BGPOptParamUnknown(type_=99, value=b'fuga')] + msg1 = bgp.BGPOpen(my_as=30000, bgp_identifier='192.0.2.2', + opt_param=opt_param) + jsondict = msg1.to_jsondict() + msg2 = bgp.BGPOpen.from_jsondict(jsondict['BGPOpen']) + eq_(str(msg1), str(msg2)) + + def test_json2(self): + withdrawn_routes = [bgp.BGPWithdrawnRoute(length=0, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=1, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=3, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=7, + addr='192.0.2.13'), + bgp.BGPWithdrawnRoute(length=32, + addr='192.0.2.13')] + mp_nlri = [ + bgp.LabelledVPNIPAddrPrefix(24, '192.0.9.0', + route_dist='100:100', + labels=[1, 2, 3]), + bgp.LabelledVPNIPAddrPrefix(26, '192.0.10.192', + route_dist='10.0.0.1:10000', + labels=[5, 6, 7, 8]), + ] + mp_nlri2 = [ + bgp.LabelledIPAddrPrefix(24, '192.168.0.0', labels=[1, 2, 3]) + ] + mp_nlri_v6 = [ + bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:1111::', + route_dist='200:200', + labels=[1, 2, 3]), + bgp.LabelledVPNIP6AddrPrefix(64, '2001:db8:2222::', + route_dist='10.0.0.1:10000', + labels=[5, 6, 7, 8]), + ] + mp_nlri2_v6 = [ + bgp.LabelledIP6AddrPrefix(64, '2001:db8:3333::', labels=[1, 2, 3]) + ] + communities = [ + bgp.BGP_COMMUNITY_NO_EXPORT, + bgp.BGP_COMMUNITY_NO_ADVERTISE, + ] + ecommunities = [ + bgp.BGPTwoOctetAsSpecificExtendedCommunity( + subtype=1, as_number=65500, local_administrator=3908876543), + bgp.BGPFourOctetAsSpecificExtendedCommunity( + subtype=2, as_number=10000000, local_administrator=59876), + bgp.BGPIPv4AddressSpecificExtendedCommunity( + subtype=3, ipv4_address='192.0.2.1', + local_administrator=65432), + bgp.BGPOpaqueExtendedCommunity(subtype=13, opaque=b'abcdef'), + bgp.BGPEncapsulationExtendedCommunity( + subtype=0x0c, tunnel_type=10), + bgp.BGPEvpnMacMobilityExtendedCommunity( + subtype=0, flags=0xff, sequence_number=0x11223344), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, label=b'\xFF\xFF\xFF'), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, mpls_label=0xfffff), + bgp.BGPEvpnEsiLabelExtendedCommunity( + subtype=1, flags=0xff, vni=0xffffff), + bgp.BGPEvpnEsImportRTExtendedCommunity( + subtype=2, es_import="aa:bb:cc:dd:ee:ff"), + bgp.BGPUnknownExtendedCommunity(type_=99, value=b'abcdefg'), + ] + path_attributes = [ + bgp.BGPPathAttributeOrigin(value=1), + bgp.BGPPathAttributeAsPath(value=[[1000], {1001, 1002}, + [1003, 1004]]), + bgp.BGPPathAttributeNextHop(value='192.0.2.199'), + bgp.BGPPathAttributeMultiExitDisc(value=2000000000), + bgp.BGPPathAttributeLocalPref(value=1000000000), + bgp.BGPPathAttributeAtomicAggregate(), + bgp.BGPPathAttributeAggregator(as_number=40000, + addr='192.0.2.99'), + bgp.BGPPathAttributeCommunities(communities=communities), + bgp.BGPPathAttributeExtendedCommunities(communities=ecommunities), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT, + label=b'\xFF\xFF\xFF'), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_NO_TUNNEL_INFORMATION_PRESENT, + tunnel_id=None), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_INGRESS_REPLICATION, + mpls_label=0xfffff, + tunnel_id=bgp.PmsiTunnelIdIngressReplication( + tunnel_endpoint_ip="1.1.1.1")), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=PMSI_TYPE_INGRESS_REPLICATION, + vni=0xffffff, + tunnel_id=bgp.PmsiTunnelIdIngressReplication( + tunnel_endpoint_ip="aa:bb:cc::dd:ee:ff")), + bgp.BGPPathAttributePmsiTunnel( + pmsi_flags=1, + tunnel_type=2, + label=b'\xFF\xFF\xFF', + tunnel_id=bgp.PmsiTunnelIdUnknown(value=b'test')), + bgp.BGPPathAttributeAs4Path(value=[[1000000], {1000001, 1002}, + [1003, 1000004]]), + bgp.BGPPathAttributeAs4Aggregator(as_number=100040000, + addr='192.0.2.99'), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, + next_hop='1.1.1.1', + nlri=mp_nlri), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP, safi=safi.MPLS_LABEL, + next_hop='1.1.1.1', + nlri=mp_nlri2), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_VPN, + next_hop=['2001:db8::1'], + nlri=mp_nlri_v6), + bgp.BGPPathAttributeMpReachNLRI(afi=afi.IP6, safi=safi.MPLS_LABEL, + next_hop=['2001:db8::1', + 'fe80::1'], + nlri=mp_nlri2_v6), + bgp.BGPPathAttributeMpUnreachNLRI(afi=afi.IP, safi=safi.MPLS_VPN, + withdrawn_routes=mp_nlri), + bgp.BGPPathAttributeUnknown(flags=0, type_=100, value=300 * b'bar') + ] + nlri = [ + bgp.BGPNLRI(length=24, addr='203.0.113.1'), + bgp.BGPNLRI(length=16, addr='203.0.113.0') + ] + msg1 = bgp.BGPUpdate(withdrawn_routes=withdrawn_routes, + path_attributes=path_attributes, + nlri=nlri) + jsondict = msg1.to_jsondict() + msg2 = bgp.BGPUpdate.from_jsondict(jsondict['BGPUpdate']) + eq_(str(msg1), str(msg2)) + + def test_flowspec_user_interface_ipv4(self): + rules = RULES_BASE + [ + # dst_prefix='10.0.0.0/24 + bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24), + # src_prefix='20.0.0.1/24' + bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24), + # ip_proto='6' + bgp.FlowSpecIPProtocol( + operator=bgp.FlowSpecIPProtocol.EQ, value=6), + # fragment='LF' + bgp.FlowSpecFragment( + operator=0, # Partial match + value=bgp.FlowSpecFragment.LF), + # fragment='==FF' + bgp.FlowSpecFragment( + operator=bgp.FlowSpecFragment.MATCH, + value=bgp.FlowSpecFragment.FF), + # fragment='&==ISF' + bgp.FlowSpecFragment( + operator=(bgp.FlowSpecFragment.AND | + bgp.FlowSpecFragment.MATCH), + value=bgp.FlowSpecFragment.ISF), + # fragment='!=DF' + bgp.FlowSpecFragment( + operator=bgp.FlowSpecFragment.NOT, + value=bgp.FlowSpecFragment.DF) + ] + + msg = bgp.FlowSpecIPv4NLRI.from_user( + dst_prefix='10.0.0.0/24', + src_prefix='20.0.0.0/24', + ip_proto='6', + port='>=8000 & <=9000 | ==80', + dst_port='8080 >9000&<9050 | <=1000', + src_port='<=9090 & >=9080 <10100 & >10000', + icmp_type=0, + icmp_code=6, + tcp_flags='SYN+ACK & !=URGENT', + packet_len='1000 & 1100', + dscp='22 24', + fragment='LF ==FF&==ISF | !=DF') + msg2 = bgp.FlowSpecIPv4NLRI(rules=rules) + binmsg = msg.serialize() + binmsg2 = msg2.serialize() + eq_(str(msg), str(msg2)) + eq_(binary_str(binmsg), binary_str(binmsg2)) + msg3, rest = bgp.FlowSpecIPv4NLRI.parser(binmsg) + eq_(str(msg), str(msg3)) + eq_(rest, b'') + + def test_flowspec_user_interface_vpv4(self): + rules = RULES_BASE + [ + # dst_prefix='10.0.0.0/24 + bgp.FlowSpecDestPrefix(addr='10.0.0.0', length=24), + # src_prefix='20.0.0.1/24' + bgp.FlowSpecSrcPrefix(addr='20.0.0.0', length=24), + # ip_proto='6' + bgp.FlowSpecIPProtocol( + operator=bgp.FlowSpecIPProtocol.EQ, value=6), + # fragment='LF' + bgp.FlowSpecFragment( + operator=0, # Partial match + value=bgp.FlowSpecFragment.LF), + # fragment='==FF' + bgp.FlowSpecFragment( + operator=bgp.FlowSpecFragment.MATCH, + value=bgp.FlowSpecFragment.FF), + # fragment='&==ISF' + bgp.FlowSpecFragment( + operator=(bgp.FlowSpecFragment.AND | + bgp.FlowSpecFragment.MATCH), + value=bgp.FlowSpecFragment.ISF), + # fragment='!=DF' + bgp.FlowSpecFragment( + operator=bgp.FlowSpecFragment.NOT, + value=bgp.FlowSpecFragment.DF) + ] + msg = bgp.FlowSpecVPNv4NLRI.from_user( + route_dist='65001:250', + dst_prefix='10.0.0.0/24', + src_prefix='20.0.0.0/24', + ip_proto='6', + port='>=8000 & <=9000 | ==80', + dst_port='8080 >9000&<9050 | <=1000', + src_port='<=9090 & >=9080 <10100 & >10000', + icmp_type=0, + icmp_code=6, + tcp_flags='SYN+ACK & !=URGENT', + packet_len='1000 & 1100', + dscp='22 24', + fragment='LF ==FF&==ISF | !=DF') + msg2 = bgp.FlowSpecVPNv4NLRI(route_dist='65001:250', rules=rules) + binmsg = msg.serialize() + binmsg2 = msg2.serialize() + eq_(str(msg), str(msg2)) + eq_(binary_str(binmsg), binary_str(binmsg2)) + msg3, rest = bgp.FlowSpecVPNv4NLRI.parser(binmsg) + eq_(str(msg), str(msg3)) + eq_(rest, b'') + + def test_flowspec_user_interface_ipv6(self): + rules = RULES_BASE + [ + # dst_prefix='2001:2/128/32' + bgp.FlowSpecIPv6DestPrefix( + addr='2001::2', offset=32, length=128), + # src_prefix='3002::3/128' + bgp.FlowSpecIPv6SrcPrefix( + addr='3002::3', length=128), + # ip_proto='6' + bgp.FlowSpecNextHeader( + operator=bgp.FlowSpecNextHeader.EQ, value=6), + # fragment='LF' + bgp.FlowSpecIPv6Fragment( + operator=0, # Partial match + value=bgp.FlowSpecFragment.LF), + # fragment='==FF' + bgp.FlowSpecIPv6Fragment( + operator=bgp.FlowSpecFragment.MATCH, + value=bgp.FlowSpecFragment.FF), + # fragment='&==ISF' + bgp.FlowSpecIPv6Fragment( + operator=(bgp.FlowSpecFragment.AND | + bgp.FlowSpecFragment.MATCH), + value=bgp.FlowSpecFragment.ISF), + # fragment='!=LF' + bgp.FlowSpecIPv6Fragment( + operator=bgp.FlowSpecFragment.NOT, + value=bgp.FlowSpecFragment.LF), + # flowlabel='100' + bgp.FlowSpecIPv6FlowLabel( + operator=bgp.FlowSpecIPv6FlowLabel.EQ, + value=100), + ] + msg = bgp.FlowSpecIPv6NLRI.from_user( + dst_prefix='2001::2/128/32', + src_prefix='3002::3/128', + next_header='6', + port='>=8000 & <=9000 | ==80', + dst_port='8080 >9000&<9050 | <=1000', + src_port='<=9090 & >=9080 <10100 & >10000', + icmp_type=0, + icmp_code=6, + tcp_flags='SYN+ACK & !=URGENT', + packet_len='1000 & 1100', + dscp='22 24', + fragment='LF ==FF&==ISF | !=LF', + flow_label=100, + ) + msg2 = bgp.FlowSpecIPv6NLRI(rules=rules) + binmsg = msg.serialize() + binmsg2 = msg2.serialize() + eq_(str(msg), str(msg2)) + eq_(binary_str(binmsg), binary_str(binmsg2)) + msg3, rest = bgp.FlowSpecIPv6NLRI.parser(binmsg) + eq_(str(msg), str(msg3)) + eq_(rest, b'') + + def test_flowspec_user_interface_vpnv6(self): + rules = RULES_BASE + [ + # dst_prefix='2001:2/128/32' + bgp.FlowSpecIPv6DestPrefix( + addr='2001::2', offset=32, length=128), + # src_prefix='3002::3/128' + bgp.FlowSpecIPv6SrcPrefix( + addr='3002::3', length=128), + # ip_proto='6' + bgp.FlowSpecNextHeader( + operator=bgp.FlowSpecNextHeader.EQ, value=6), + # fragment='LF' + bgp.FlowSpecIPv6Fragment( + operator=0, # Partial match + value=bgp.FlowSpecFragment.LF), + # fragment='==FF' + bgp.FlowSpecIPv6Fragment( + operator=bgp.FlowSpecFragment.MATCH, + value=bgp.FlowSpecFragment.FF), + # fragment='&==ISF' + bgp.FlowSpecIPv6Fragment( + operator=(bgp.FlowSpecFragment.AND | + bgp.FlowSpecFragment.MATCH), + value=bgp.FlowSpecFragment.ISF), + # fragment='!=LF' + bgp.FlowSpecIPv6Fragment( + operator=bgp.FlowSpecFragment.NOT, + value=bgp.FlowSpecFragment.LF), + # flowlabel='100' + bgp.FlowSpecIPv6FlowLabel( + operator=bgp.FlowSpecIPv6FlowLabel.EQ, + value=100), + ] + msg = bgp.FlowSpecVPNv6NLRI.from_user( + route_dist='65001:250', + dst_prefix='2001::2/128/32', + src_prefix='3002::3/128', + next_header='6', + port='>=8000 & <=9000 | ==80', + dst_port='8080 >9000&<9050 | <=1000', + src_port='<=9090 & >=9080 <10100 & >10000', + icmp_type=0, + icmp_code=6, + tcp_flags='SYN+ACK & !=URGENT', + packet_len='1000 & 1100', + dscp='22 24', + fragment='LF ==FF&==ISF | !=LF', + flow_label=100, + ) + msg2 = bgp.FlowSpecVPNv6NLRI(route_dist='65001:250', rules=rules) + binmsg = msg.serialize() + binmsg2 = msg2.serialize() + eq_(str(msg), str(msg2)) + eq_(binary_str(binmsg), binary_str(binmsg2)) + msg3, rest = bgp.FlowSpecVPNv6NLRI.parser(binmsg) + eq_(str(msg), str(msg3)) + eq_(rest, b'') + + def test_flowspec_user_interface_l2vpn(self): + rules = RULES_L2VPN_BASE + msg = bgp.FlowSpecL2VPNNLRI.from_user( + route_dist='65001:250', + ether_type=0x0800, + src_mac='12:34:56:78:90:AB', + dst_mac='BE:EF:C0:FF:EE:DD', + llc_dsap=0x42, + llc_ssap=0x42, + llc_control=100, + snap=0x12345, + vlan_id='>4000', + vlan_cos='>=3', + inner_vlan_id='<3000', + inner_vlan_cos='<=5', + ) + msg2 = bgp.FlowSpecL2VPNNLRI(route_dist='65001:250', rules=rules) + binmsg = msg.serialize() + binmsg2 = msg2.serialize() + eq_(str(msg), str(msg2)) + eq_(binary_str(binmsg), binary_str(binmsg2)) + msg3, rest = bgp.FlowSpecL2VPNNLRI.parser(binmsg) + eq_(str(msg), str(msg3)) + eq_(rest, b'') |