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 16from collections import OrderedDict 17import unittest 18import logging 19try: 20 import mock # Python 2 21except ImportError: 22 from unittest import mock # Python 3 23 24from nose.tools import ok_, eq_, raises 25 26from ryu.lib.packet.bgp import BGPPathAttributeOrigin 27from ryu.lib.packet.bgp import BGPPathAttributeAsPath 28from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP 29from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN 30from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH 31from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES 32from ryu.lib.packet.bgp import IPAddrPrefix 33from ryu.lib.packet.bgp import IP6AddrPrefix 34from ryu.lib.packet.bgp import EvpnArbitraryEsi 35from ryu.lib.packet.bgp import EvpnLACPEsi 36from ryu.lib.packet.bgp import EvpnEthernetAutoDiscoveryNLRI 37from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI 38from ryu.lib.packet.bgp import EvpnInclusiveMulticastEthernetTagNLRI 39from ryu.lib.packet.bgp import FlowSpecIPv4NLRI 40from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities 41from ryu.services.protocols.bgp.bgpspeaker import EVPN_MAX_ET 42from ryu.services.protocols.bgp.bgpspeaker import ESI_TYPE_LACP 43from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_IPV4 44from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_VPNV4 45from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TA_SAMPLE 46from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TA_TERMINAL 47from ryu.services.protocols.bgp.core import BgpCoreError 48from ryu.services.protocols.bgp.core_managers import table_manager 49from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4 50from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV6 51from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_L2_EVPN 52from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4_FLOWSPEC 53from ryu.services.protocols.bgp.utils.bgp import create_v4flowspec_actions 54 55 56LOG = logging.getLogger(__name__) 57 58 59class Test_TableCoreManager(unittest.TestCase): 60 """ 61 Test case for bgp.core_managers.table_manager.TableCoreManager 62 """ 63 64 @mock.patch( 65 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 66 mock.MagicMock(return_value=None)) 67 def _test_update_vrf_table(self, prefix_inst, route_dist, prefix_str, 68 next_hop, route_family, route_type, 69 is_withdraw=False, **kwargs): 70 # Instantiate TableCoreManager 71 tbl_mng = table_manager.TableCoreManager(None, None) 72 vrf_table_mock = mock.MagicMock() 73 tbl_mng._tables = {(route_dist, route_family): vrf_table_mock} 74 75 # Test 76 tbl_mng.update_vrf_table( 77 route_dist=route_dist, 78 prefix=prefix_str, 79 next_hop=next_hop, 80 route_family=route_family, 81 route_type=route_type, 82 is_withdraw=is_withdraw, 83 **kwargs) 84 85 # Check 86 call_args_list = vrf_table_mock.insert_vrf_path.call_args_list 87 ok_(len(call_args_list) == 1) # insert_vrf_path should be called once 88 args, kwargs = call_args_list[0] 89 ok_(len(args) == 0) # no positional argument 90 eq_(str(prefix_inst), str(kwargs['nlri'])) 91 eq_(is_withdraw, kwargs['is_withdraw']) 92 if is_withdraw: 93 eq_(None, kwargs['next_hop']) 94 eq_(False, kwargs['gen_lbl']) 95 else: 96 eq_(next_hop, kwargs['next_hop']) 97 eq_(True, kwargs['gen_lbl']) 98 99 def test_update_vrf_table_ipv4(self): 100 # Prepare test data 101 route_dist = '65000:100' 102 ip_network = '192.168.0.0' 103 ip_prefix_len = 24 104 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 105 prefix_inst = IPAddrPrefix(ip_prefix_len, ip_network) 106 next_hop = '10.0.0.1' 107 route_family = VRF_RF_IPV4 108 route_type = None # should be ignored 109 kwargs = {} # should be ignored 110 111 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 112 next_hop, route_family, route_type, 113 **kwargs) 114 115 def test_update_vrf_table_ipv6(self): 116 # Prepare test data 117 route_dist = '65000:100' 118 ip_network = 'fe80::' 119 ip_prefix_len = 64 120 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 121 prefix_inst = IP6AddrPrefix(ip_prefix_len, ip_network) 122 next_hop = 'fe80::0011:aabb:ccdd:eeff' 123 route_family = VRF_RF_IPV6 124 route_type = None # should be ignored 125 kwargs = {} # should be ignored 126 127 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 128 next_hop, route_family, route_type, 129 **kwargs) 130 131 def test_update_vrf_table_l2_evpn_with_esi_int(self): 132 # Prepare test data 133 route_dist = '65000:100' 134 prefix_str = None # should be ignored 135 kwargs = { 136 'ethernet_tag_id': 100, 137 'mac_addr': 'aa:bb:cc:dd:ee:ff', 138 'ip_addr': '192.168.0.1', 139 'mpls_labels': [], # not be used 140 } 141 esi = EvpnArbitraryEsi(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00') 142 prefix_inst = EvpnMacIPAdvertisementNLRI( 143 route_dist=route_dist, 144 esi=esi, 145 **kwargs) 146 next_hop = '10.0.0.1' 147 route_family = VRF_RF_L2_EVPN 148 route_type = EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME 149 kwargs['esi'] = 0 150 151 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 152 next_hop, route_family, route_type, 153 **kwargs) 154 155 def test_update_vrf_table_l2_evpn_with_esi_dict(self): 156 # Prepare test data 157 route_dist = '65000:100' 158 prefix_str = None # should be ignored 159 kwargs = { 160 'ethernet_tag_id': EVPN_MAX_ET, 161 } 162 esi = EvpnLACPEsi(mac_addr='aa:bb:cc:dd:ee:ff', port_key=100) 163 prefix_inst = EvpnEthernetAutoDiscoveryNLRI( 164 route_dist=route_dist, 165 esi=esi, 166 **kwargs) 167 next_hop = '0.0.0.0' 168 route_family = VRF_RF_L2_EVPN 169 route_type = EvpnEthernetAutoDiscoveryNLRI.ROUTE_TYPE_NAME 170 kwargs['esi'] = { 171 'type': ESI_TYPE_LACP, 172 'mac_addr': 'aa:bb:cc:dd:ee:ff', 173 'port_key': 100, 174 } 175 176 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 177 next_hop, route_family, route_type, 178 **kwargs) 179 180 def test_update_vrf_table_l2_evpn_without_esi(self): 181 # Prepare test data 182 route_dist = '65000:100' 183 prefix_str = None # should be ignored 184 kwargs = { 185 'ethernet_tag_id': 100, 186 'ip_addr': '192.168.0.1', 187 } 188 prefix_inst = EvpnInclusiveMulticastEthernetTagNLRI( 189 route_dist=route_dist, **kwargs) 190 next_hop = '10.0.0.1' 191 route_family = VRF_RF_L2_EVPN 192 route_type = EvpnInclusiveMulticastEthernetTagNLRI.ROUTE_TYPE_NAME 193 194 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 195 next_hop, route_family, route_type, 196 **kwargs) 197 198 @mock.patch( 199 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 200 mock.MagicMock(return_value=None)) 201 def test_update_vrf_table_l2_evpn_with_vni(self): 202 # Prepare test data 203 route_dist = '65000:100' 204 prefix_str = None # should be ignored 205 kwargs = { 206 'ethernet_tag_id': 100, 207 'mac_addr': 'aa:bb:cc:dd:ee:ff', 208 'ip_addr': '192.168.0.1', 209 'vni': 500, 210 } 211 esi = EvpnArbitraryEsi(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00') 212 prefix_inst = EvpnMacIPAdvertisementNLRI( 213 route_dist=route_dist, 214 esi=esi, 215 **kwargs) 216 next_hop = '10.0.0.1' 217 route_family = VRF_RF_L2_EVPN 218 route_type = EvpnMacIPAdvertisementNLRI.ROUTE_TYPE_NAME 219 tunnel_type = 'vxlan' 220 kwargs['esi'] = 0 221 222 # Instantiate TableCoreManager 223 tbl_mng = table_manager.TableCoreManager(None, None) 224 vrf_table_mock = mock.MagicMock() 225 tbl_mng._tables = {(route_dist, route_family): vrf_table_mock} 226 227 # Test 228 tbl_mng.update_vrf_table( 229 route_dist=route_dist, 230 prefix=prefix_str, 231 next_hop=next_hop, 232 route_family=route_family, 233 route_type=route_type, 234 tunnel_type=tunnel_type, 235 **kwargs) 236 237 # Check 238 call_args_list = vrf_table_mock.insert_vrf_path.call_args_list 239 ok_(len(call_args_list) == 1) # insert_vrf_path should be called once 240 args, kwargs = call_args_list[0] 241 ok_(len(args) == 0) # no positional argument 242 eq_(str(prefix_inst), str(kwargs['nlri'])) 243 eq_(next_hop, kwargs['next_hop']) 244 eq_(False, kwargs['gen_lbl']) # should not generate MPLS labels 245 eq_(tunnel_type, kwargs['tunnel_type']) 246 247 def test_update_vrf_table_ipv4_withdraw(self): 248 # Prepare test data 249 route_dist = '65000:100' 250 ip_network = '192.168.0.0' 251 ip_prefix_len = 24 252 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 253 prefix_inst = IPAddrPrefix(ip_prefix_len, ip_network) 254 next_hop = '10.0.0.1' 255 route_family = VRF_RF_IPV4 256 route_type = None # should be ignored 257 kwargs = {} # should be ignored 258 259 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 260 next_hop, route_family, route_type, 261 is_withdraw=True, **kwargs) 262 263 @raises(BgpCoreError) 264 @mock.patch( 265 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 266 mock.MagicMock(return_value=None)) 267 def test_update_vrf_table_no_vrf(self): 268 # Prepare test data 269 route_dist = '65000:100' 270 ip_network = '192.168.0.0' 271 ip_prefix_len = 24 272 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 273 next_hop = '10.0.0.1' 274 route_family = VRF_RF_IPV4 275 route_type = None # should be ignored 276 kwargs = {} # should be ignored 277 278 # Instantiate TableCoreManager 279 tbl_mng = table_manager.TableCoreManager(None, None) 280 tbl_mng._tables = {} # no table 281 282 # Test 283 tbl_mng.update_vrf_table( 284 route_dist=route_dist, 285 prefix=prefix_str, 286 next_hop=next_hop, 287 route_family=route_family, 288 route_type=route_type, 289 **kwargs) 290 291 @raises(BgpCoreError) 292 def test_update_vrf_table_invalid_next_hop(self): 293 # Prepare test data 294 route_dist = '65000:100' 295 ip_network = '192.168.0.0' 296 ip_prefix_len = 24 297 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 298 prefix_inst = IPAddrPrefix(ip_prefix_len, ip_network) 299 next_hop = 'xxx.xxx.xxx.xxx' # invalid 300 route_family = VRF_RF_IPV4 301 route_type = None # should be ignored 302 kwargs = {} # should be ignored 303 304 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 305 next_hop, route_family, route_type, 306 **kwargs) 307 308 @raises(BgpCoreError) 309 def test_update_vrf_table_invalid_ipv4_prefix(self): 310 # Prepare test data 311 route_dist = '65000:100' 312 ip_network = 'xxx.xxx.xxx.xxx' # invalid 313 ip_prefix_len = 24 314 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 315 prefix_inst = IPAddrPrefix(ip_prefix_len, ip_network) 316 next_hop = '10.0.0.1' 317 route_family = VRF_RF_IPV4 318 route_type = None # should be ignored 319 kwargs = {} # should be ignored 320 321 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 322 next_hop, route_family, route_type, 323 **kwargs) 324 325 @raises(BgpCoreError) 326 def test_update_vrf_table_invalid_ipv6_prefix(self): 327 # Prepare test data 328 route_dist = '65000:100' 329 ip_network = 'xxxx::' # invalid 330 ip_prefix_len = 64 331 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 332 prefix_inst = IP6AddrPrefix(ip_prefix_len, ip_network) 333 next_hop = 'fe80::0011:aabb:ccdd:eeff' 334 route_family = VRF_RF_IPV6 335 route_type = None # should be ignored 336 kwargs = {} # should be ignored 337 338 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 339 next_hop, route_family, route_type, 340 **kwargs) 341 342 @raises(BgpCoreError) 343 def test_update_vrf_table_invalid_route_family(self): 344 # Prepare test data 345 route_dist = '65000:100' 346 ip_network = '192.168.0.0' 347 ip_prefix_len = 24 348 prefix_str = '%s/%d' % (ip_network, ip_prefix_len) 349 prefix_inst = IPAddrPrefix(ip_prefix_len, ip_network) 350 next_hop = '10.0.0.1' 351 route_family = 'foobar' # invalid 352 route_type = None # should be ignored 353 kwargs = {} # should be ignored 354 355 self._test_update_vrf_table(prefix_inst, route_dist, prefix_str, 356 next_hop, route_family, route_type, 357 **kwargs) 358 359 @mock.patch( 360 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 361 mock.MagicMock(return_value=None)) 362 @mock.patch( 363 'ryu.services.protocols.bgp.core_managers.TableCoreManager.learn_path') 364 def _test_update_global_table(self, learn_path_mock, prefix, next_hop, 365 is_withdraw, expected_next_hop): 366 # Prepare test data 367 origin = BGPPathAttributeOrigin(BGP_ATTR_ORIGIN_IGP) 368 aspath = BGPPathAttributeAsPath([[]]) 369 pathattrs = OrderedDict() 370 pathattrs[BGP_ATTR_TYPE_ORIGIN] = origin 371 pathattrs[BGP_ATTR_TYPE_AS_PATH] = aspath 372 pathattrs = str(pathattrs) 373 374 # Instantiate TableCoreManager 375 tbl_mng = table_manager.TableCoreManager(None, None) 376 377 # Test 378 tbl_mng.update_global_table( 379 prefix=prefix, 380 next_hop=next_hop, 381 is_withdraw=is_withdraw, 382 ) 383 384 # Check 385 call_args_list = learn_path_mock.call_args_list 386 ok_(len(call_args_list) == 1) # learn_path should be called once 387 args, kwargs = call_args_list[0] 388 ok_(len(kwargs) == 0) # no keyword argument 389 output_path = args[0] 390 eq_(None, output_path.source) 391 eq_(prefix, output_path.nlri.prefix) 392 eq_(pathattrs, str(output_path.pathattr_map)) 393 eq_(expected_next_hop, output_path.nexthop) 394 eq_(is_withdraw, output_path.is_withdraw) 395 396 def test_update_global_table_ipv4(self): 397 self._test_update_global_table( 398 prefix='192.168.0.0/24', 399 next_hop='10.0.0.1', 400 is_withdraw=False, 401 expected_next_hop='10.0.0.1', 402 ) 403 404 def test_update_global_table_ipv4_withdraw(self): 405 self._test_update_global_table( 406 prefix='192.168.0.0/24', 407 next_hop='10.0.0.1', 408 is_withdraw=True, 409 expected_next_hop='10.0.0.1', 410 ) 411 412 def test_update_global_table_ipv4_no_next_hop(self): 413 self._test_update_global_table( 414 prefix='192.168.0.0/24', 415 next_hop=None, 416 is_withdraw=True, 417 expected_next_hop='0.0.0.0', 418 ) 419 420 def test_update_global_table_ipv6(self): 421 self._test_update_global_table( 422 prefix='fe80::/64', 423 next_hop='fe80::0011:aabb:ccdd:eeff', 424 is_withdraw=False, 425 expected_next_hop='fe80::0011:aabb:ccdd:eeff', 426 ) 427 428 def test_update_global_table_ipv6_withdraw(self): 429 self._test_update_global_table( 430 prefix='fe80::/64', 431 next_hop='fe80::0011:aabb:ccdd:eeff', 432 is_withdraw=True, 433 expected_next_hop='fe80::0011:aabb:ccdd:eeff', 434 ) 435 436 def test_update_global_table_ipv6_no_next_hop(self): 437 self._test_update_global_table( 438 prefix='fe80::/64', 439 next_hop=None, 440 is_withdraw=True, 441 expected_next_hop='::', 442 ) 443 444 @mock.patch( 445 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 446 mock.MagicMock(return_value=None)) 447 def _test_update_flowspec_vrf_table(self, flowspec_family, route_family, 448 route_dist, rules, prefix, 449 is_withdraw, actions=None): 450 # Instantiate TableCoreManager 451 tbl_mng = table_manager.TableCoreManager(None, None) 452 vrf_table_mock = mock.MagicMock() 453 tbl_mng._tables = {(route_dist, route_family): vrf_table_mock} 454 455 # Test 456 tbl_mng.update_flowspec_vrf_table( 457 flowspec_family=flowspec_family, 458 route_dist=route_dist, 459 rules=rules, 460 actions=actions, 461 is_withdraw=is_withdraw, 462 ) 463 464 # Check 465 call_args_list = vrf_table_mock.insert_vrffs_path.call_args_list 466 ok_(len( 467 call_args_list) == 1) # insert_vrffs_path should be called once 468 args, kwargs = call_args_list[0] 469 ok_(len(args) == 0) # no positional argument 470 eq_(prefix, kwargs['nlri'].prefix) 471 eq_(is_withdraw, kwargs['is_withdraw']) 472 473 def test_update_flowspec_vrf_table_vpnv4(self): 474 flowspec_family = 'vpnv4fs' 475 route_family = 'ipv4fs' 476 route_dist = '65001:100' 477 rules = { 478 'dst_prefix': '10.70.1.0/24', 479 } 480 actions = { 481 'traffic_rate': { 482 'as_number': 0, 483 'rate_info': 100.0, 484 }, 485 } 486 prefix = 'ipv4fs(dst_prefix:10.70.1.0/24)' 487 488 self._test_update_flowspec_vrf_table( 489 flowspec_family=flowspec_family, 490 route_family=route_family, 491 route_dist=route_dist, 492 rules=rules, 493 prefix=prefix, 494 is_withdraw=False, 495 actions=actions, 496 ) 497 498 def test_update_flowspec_vrf_table_vpnv4_without_actions(self): 499 flowspec_family = 'vpnv4fs' 500 route_family = 'ipv4fs' 501 route_dist = '65001:100' 502 rules = { 503 'dst_prefix': '10.70.1.0/24', 504 } 505 prefix = 'ipv4fs(dst_prefix:10.70.1.0/24)' 506 507 self._test_update_flowspec_vrf_table( 508 flowspec_family=flowspec_family, 509 route_family=route_family, 510 route_dist=route_dist, 511 rules=rules, 512 prefix=prefix, 513 is_withdraw=False, 514 ) 515 516 @raises(BgpCoreError) 517 def test_update_flowspec_vrf_table_vpnv4_invalid_actions(self): 518 flowspec_family = 'vpnv4fs' 519 route_family = 'ipv4fs' 520 route_dist = '65001:100' 521 rules = { 522 'dst_prefix': '10.70.1.0/24', 523 } 524 actions = { 525 'invalid_actions': { 526 'invalid_param': 10, 527 }, 528 } 529 prefix = 'ipv4fs(dst_prefix:10.70.1.0/24)' 530 531 self._test_update_flowspec_vrf_table( 532 flowspec_family=flowspec_family, 533 route_family=route_family, 534 route_dist=route_dist, 535 rules=rules, 536 prefix=prefix, 537 is_withdraw=False, 538 actions=actions, 539 ) 540 541 @raises(BgpCoreError) 542 def test_update_flowspec_vrf_table_vpnv4_invalid_flowspec_family(self): 543 flowspec_family = 'invalid' 544 route_family = 'ipv4fs' 545 route_dist = '65001:100' 546 rules = { 547 'dst_prefix': '10.70.1.0/24', 548 } 549 prefix = 'ipv4fs(dst_prefix:10.70.1.0/24)' 550 551 self._test_update_flowspec_vrf_table( 552 flowspec_family=flowspec_family, 553 route_family=route_family, 554 route_dist=route_dist, 555 rules=rules, 556 prefix=prefix, 557 is_withdraw=False, 558 ) 559 560 @raises(BgpCoreError) 561 def test_update_flowspec_vrf_table_vpnv4_invalid_route_family(self): 562 flowspec_family = 'vpnv4fs' 563 route_family = 'invalid' 564 route_dist = '65001:100' 565 rules = { 566 'dst_prefix': '10.70.1.0/24', 567 } 568 prefix = 'ipv4fs(dst_prefix:10.70.1.0/24)' 569 570 self._test_update_flowspec_vrf_table( 571 flowspec_family=flowspec_family, 572 route_family=route_family, 573 route_dist=route_dist, 574 rules=rules, 575 prefix=prefix, 576 is_withdraw=False, 577 ) 578 579 @mock.patch( 580 'ryu.services.protocols.bgp.core_managers.TableCoreManager.__init__', 581 mock.MagicMock(return_value=None)) 582 @mock.patch( 583 'ryu.services.protocols.bgp.core_managers.TableCoreManager.learn_path') 584 def _test_update_flowspec_global_table(self, learn_path_mock, 585 flowspec_family, rules, prefix, 586 is_withdraw, actions=None): 587 # Instantiate TableCoreManager 588 tbl_mng = table_manager.TableCoreManager(None, None) 589 590 # Test 591 tbl_mng.update_flowspec_global_table( 592 flowspec_family=flowspec_family, 593 rules=rules, 594 actions=actions, 595 is_withdraw=is_withdraw, 596 ) 597 598 # Check 599 call_args_list = learn_path_mock.call_args_list 600 ok_(len(call_args_list) == 1) # learn_path should be called once 601 args, kwargs = call_args_list[0] 602 ok_(len(kwargs) == 0) # no keyword argument 603 output_path = args[0] 604 eq_(None, output_path.source) 605 eq_(prefix, output_path.nlri.prefix) 606 eq_(None, output_path.nexthop) 607 eq_(is_withdraw, output_path.is_withdraw) 608 609 def test_update_flowspec_global_table_ipv4(self): 610 flowspec_family = 'ipv4fs' 611 rules = { 612 'dst_prefix': '10.60.1.0/24', 613 } 614 actions = { 615 'traffic_rate': { 616 'as_number': 0, 617 'rate_info': 100.0, 618 }, 619 } 620 prefix = 'ipv4fs(dst_prefix:10.60.1.0/24)' 621 622 self._test_update_flowspec_global_table( 623 flowspec_family=flowspec_family, 624 rules=rules, 625 prefix=prefix, 626 is_withdraw=False, 627 actions=actions, 628 ) 629 630 def test_update_flowspec_global_table_ipv4_without_actions(self): 631 flowspec_family = 'ipv4fs' 632 rules = { 633 'dst_prefix': '10.60.1.0/24', 634 } 635 prefix = 'ipv4fs(dst_prefix:10.60.1.0/24)' 636 637 self._test_update_flowspec_global_table( 638 flowspec_family=flowspec_family, 639 rules=rules, 640 prefix=prefix, 641 is_withdraw=False, 642 ) 643 644 @raises(BgpCoreError) 645 def test_update_flowspec_global_table_ipv4_invalid_actions(self): 646 flowspec_family = 'ipv4fs' 647 rules = { 648 'dst_prefix': '10.60.1.0/24', 649 } 650 actions = { 651 'invalid_actions': { 652 'invalid_param': 10, 653 }, 654 } 655 prefix = 'ipv4fs(dst_prefix:10.60.1.0/24)' 656 657 self._test_update_flowspec_global_table( 658 flowspec_family=flowspec_family, 659 rules=rules, 660 prefix=prefix, 661 is_withdraw=False, 662 actions=actions, 663 ) 664 665 @raises(BgpCoreError) 666 def test_update_flowspec_global_table_ipv4_invalid_flowspec_family(self): 667 flowspec_family = 'invalid' 668 rules = { 669 'dst_prefix': '10.60.1.0/24', 670 } 671 actions = { 672 'traffic_rate': { 673 'as_number': 0, 674 'rate_info': 100.0, 675 }, 676 } 677 prefix = 'ipv4fs(dst_prefix:10.60.1.0/24)' 678 679 self._test_update_flowspec_global_table( 680 flowspec_family=flowspec_family, 681 rules=rules, 682 prefix=prefix, 683 is_withdraw=False, 684 actions=actions, 685 ) 686 687 def test_update_flowspec_global_table_ipv6(self): 688 flowspec_family = 'ipv6fs' 689 rules = { 690 'dst_prefix': '2001::3/128/32', 691 } 692 actions = { 693 'traffic_rate': { 694 'as_number': 0, 695 'rate_info': 100.0, 696 }, 697 } 698 prefix = 'ipv6fs(dst_prefix:2001::3/128/32)' 699 700 self._test_update_flowspec_global_table( 701 flowspec_family=flowspec_family, 702 rules=rules, 703 prefix=prefix, 704 is_withdraw=False, 705 actions=actions, 706 ) 707 708 def test_update_flowspec_global_table_ipv6_without_actions(self): 709 flowspec_family = 'ipv6fs' 710 rules = { 711 'dst_prefix': '2001::3/128/32', 712 } 713 prefix = 'ipv6fs(dst_prefix:2001::3/128/32)' 714 715 self._test_update_flowspec_global_table( 716 flowspec_family=flowspec_family, 717 rules=rules, 718 prefix=prefix, 719 is_withdraw=False, 720 ) 721 722 @raises(BgpCoreError) 723 def test_update_flowspec_global_table_ipv6_invalid_actions(self): 724 flowspec_family = 'ipv6fs' 725 rules = { 726 'dst_prefix': '2001::3/128/32', 727 } 728 actions = { 729 'invalid_actions': { 730 'invalid_param': 10, 731 }, 732 } 733 prefix = 'ipv4fs(dst_prefix:2001::3/128/32)' 734 735 self._test_update_flowspec_global_table( 736 flowspec_family=flowspec_family, 737 rules=rules, 738 prefix=prefix, 739 is_withdraw=False, 740 actions=actions, 741 ) 742 743 @raises(BgpCoreError) 744 def test_update_flowspec_global_table_ipv6_invalid_flowspec_family(self): 745 flowspec_family = 'invalid' 746 rules = { 747 'dst_prefix': '2001::3/128/32', 748 } 749 actions = { 750 'traffic_rate': { 751 'as_number': 0, 752 'rate_info': 100.0, 753 }, 754 } 755 prefix = 'ipv4fs(dst_prefix:2001::3/128/32)' 756 757 self._test_update_flowspec_global_table( 758 flowspec_family=flowspec_family, 759 rules=rules, 760 prefix=prefix, 761 is_withdraw=False, 762 actions=actions, 763 ) 764 765 def test_update_flowspec_vrf_table_vpnv6(self): 766 flowspec_family = 'vpnv6fs' 767 route_family = 'ipv6fs' 768 route_dist = '65001:100' 769 rules = { 770 'dst_prefix': '2001::3/128/32', 771 } 772 actions = { 773 'traffic_rate': { 774 'as_number': 0, 775 'rate_info': 100.0, 776 }, 777 } 778 prefix = 'ipv6fs(dst_prefix:2001::3/128/32)' 779 780 self._test_update_flowspec_vrf_table( 781 flowspec_family=flowspec_family, 782 route_family=route_family, 783 route_dist=route_dist, 784 rules=rules, 785 prefix=prefix, 786 is_withdraw=False, 787 actions=actions, 788 ) 789 790 def test_update_flowspec_vrf_table_vpnv6_without_actions(self): 791 flowspec_family = 'vpnv6fs' 792 route_family = 'ipv6fs' 793 route_dist = '65001:100' 794 rules = { 795 'dst_prefix': '2001::3/128/32', 796 } 797 prefix = 'ipv6fs(dst_prefix:2001::3/128/32)' 798 799 self._test_update_flowspec_vrf_table( 800 flowspec_family=flowspec_family, 801 route_family=route_family, 802 route_dist=route_dist, 803 rules=rules, 804 prefix=prefix, 805 is_withdraw=False, 806 ) 807 808 @raises(BgpCoreError) 809 def test_update_flowspec_vrf_table_vpnv6_invalid_actions(self): 810 flowspec_family = 'vpnv6fs' 811 route_family = 'ipv6fs' 812 route_dist = '65001:100' 813 rules = { 814 'dst_prefix': '2001::3/128/32', 815 } 816 actions = { 817 'invalid_actions': { 818 'invalid_param': 10, 819 }, 820 } 821 prefix = 'ipv6fs(dst_prefix:2001::3/128/32)' 822 823 self._test_update_flowspec_vrf_table( 824 flowspec_family=flowspec_family, 825 route_family=route_family, 826 route_dist=route_dist, 827 rules=rules, 828 prefix=prefix, 829 is_withdraw=False, 830 actions=actions, 831 ) 832 833 @raises(BgpCoreError) 834 def test_update_flowspec_vrf_table_vpnv6_invalid_route_family(self): 835 flowspec_family = 'vpnv6fs' 836 route_family = 'invalid' 837 route_dist = '65001:100' 838 rules = { 839 'dst_prefix': '2001::3/128/32', 840 } 841 prefix = 'ipv4fs(dst_prefix:2001::3/128/32)' 842 843 self._test_update_flowspec_vrf_table( 844 flowspec_family=flowspec_family, 845 route_family=route_family, 846 route_dist=route_dist, 847 rules=rules, 848 prefix=prefix, 849 is_withdraw=False, 850 ) 851 852 def test_update_flowspec_vrf_table_l2vpn(self): 853 flowspec_family = 'l2vpnfs' 854 route_family = 'l2vpnfs' 855 route_dist = '65001:100' 856 rules = { 857 'dst_mac': '12:34:56:78:9a:bc', 858 } 859 actions = { 860 'traffic_rate': { 861 'as_number': 0, 862 'rate_info': 100.0, 863 }, 864 } 865 prefix = 'l2vpnfs(dst_mac:12:34:56:78:9a:bc)' 866 867 self._test_update_flowspec_vrf_table( 868 flowspec_family=flowspec_family, 869 route_family=route_family, 870 route_dist=route_dist, 871 rules=rules, 872 prefix=prefix, 873 is_withdraw=False, 874 actions=actions, 875 ) 876 877 def test_update_flowspec_vrf_table_l2vpn_without_actions(self): 878 flowspec_family = 'l2vpnfs' 879 route_family = 'l2vpnfs' 880 route_dist = '65001:100' 881 rules = { 882 'dst_mac': '12:34:56:78:9a:bc', 883 } 884 prefix = 'l2vpnfs(dst_mac:12:34:56:78:9a:bc)' 885 886 self._test_update_flowspec_vrf_table( 887 flowspec_family=flowspec_family, 888 route_family=route_family, 889 route_dist=route_dist, 890 rules=rules, 891 prefix=prefix, 892 is_withdraw=False, 893 ) 894 895 @raises(BgpCoreError) 896 def test_update_flowspec_vrf_table_l2vpn_invalid_actions(self): 897 flowspec_family = 'l2vpnfs' 898 route_family = 'l2vpnfs' 899 route_dist = '65001:100' 900 rules = { 901 'dst_mac': '12:34:56:78:9a:bc', 902 } 903 actions = { 904 'invalid_actions': { 905 'invalid_param': 10, 906 }, 907 } 908 prefix = 'l2vpnfs(dst_mac:12:34:56:78:9a:bc)' 909 910 self._test_update_flowspec_vrf_table( 911 flowspec_family=flowspec_family, 912 route_family=route_family, 913 route_dist=route_dist, 914 rules=rules, 915 prefix=prefix, 916 is_withdraw=False, 917 actions=actions, 918 ) 919 920 @raises(BgpCoreError) 921 def test_update_flowspec_vrf_table_l2vpn_invalid_route_family(self): 922 flowspec_family = 'l2vpnfs' 923 route_family = 'invalid' 924 route_dist = '65001:100' 925 rules = { 926 'dst_mac': '12:34:56:78:9a:bc', 927 } 928 prefix = 'l2vpnfs(dst_mac:12:34:56:78:9a:bc)' 929 930 self._test_update_flowspec_vrf_table( 931 flowspec_family=flowspec_family, 932 route_family=route_family, 933 route_dist=route_dist, 934 rules=rules, 935 prefix=prefix, 936 is_withdraw=False, 937 ) 938