Пример #1
0
    def test_basic_uncfg(self):
        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='nxos')
        dev2 = Device(testbed=testbed, name='PE2', os='nxos')

        rpl1 = RoutePolicy(policy_definition='rpl1',
                           route_disposition='permit')
        dev1.add_feature(rpl1)

        rpl1.device_attr[dev1].statement_attr['10']
        rpl1.device_attr[dev1].statement_attr['10'].match_med_eq = 5

        # Unconfig testing
        # Set a mock
        dev1.configure = Mock()
        dev1.add_feature(rpl1)
        # Mock config

        uncfg1 = rpl1.build_unconfig(apply=False)
        self.assertCountEqual(uncfg1.keys(), ['PE1'])
        self.assertMultiLineEqual(str(uncfg1['PE1']),
                                  '\n'.join(['no route-map rpl1 permit 10']))

        partial_uncfg1 = rpl1.build_unconfig(
                            apply=False,
                            attributes={'device_attr':{'*':{'statement_attr':\
                                       {'*':"match_med_eq"}}}})

        self.assertCountEqual(partial_uncfg1.keys(), ['PE1'])
        self.assertMultiLineEqual(
            str(partial_uncfg1['PE1']), '\n'.join(
                ['route-map rpl1 permit 10', ' no match metric 5', ' exit']))
Пример #2
0
    def test_basic_uncfg_with_name(self):
        '''
            Testing in case of having 'name' as the route-policy name.
        '''

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='iosxr')

        rpl1 = RoutePolicy(name='rpl1')
        dev1.add_feature(rpl1)

        rpl1.device_attr[dev1].statement_attr['10']
        rpl1.device_attr[dev1].statement_attr['10'].match_med_eq = 5
        rpl1.device_attr[dev1].statement_attr['10'].match_nexthop_in = 'hop'
        rpl1.device_attr[dev1].statement_attr['10'].actions = 'pass'

        # Unconfig testing
        # Set a mock
        dev1.configure = Mock()
        dev1.add_feature(rpl1)
        # Mock config

        uncfg1 = rpl1.build_unconfig(apply=False)
        self.assertCountEqual(uncfg1.keys(), ['PE1'])
        self.assertMultiLineEqual(str(uncfg1['PE1']), '\n'.join(
            ['no route-policy rpl1'
            ]))
Пример #3
0
    def test_basic_cfg(self):

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='nxos')
        intf1 = Interface(device=dev1,
                          name='Ethernet0/0/1',
                          ipv4='10.1.0.1/24')
        intf2 = Interface(device=dev1,
                          name='Ethernet0/0/2',
                          ipv4='10.2.0.1/24')
        dev2 = Device(testbed=testbed, name='PE2', os='nxos')
        intf3 = Interface(device=dev2,
                          name='Ethernet0/0/3',
                          ipv4='10.1.0.2/24',
                          ipv6='2001:111:222::/64')
        intf4 = Interface(device=dev2,
                          name='Ethernet0/0/4',
                          ipv4='10.2.0.2/24')

        rpl1 = RoutePolicy(policy_definition='rpl1',
                           route_disposition='permit')
        dev1.add_feature(rpl1)

        rpl1.device_attr[dev1].statement_attr['10']
        rpl1.device_attr[dev1].statement_attr['10'].match_med_eq = 5

        cfgs = rpl1.build_config(apply=False)
        self.assertCountEqual(cfgs.keys(), [dev1.name])
        self.assertMultiLineEqual(
            str(cfgs[dev1.name]),
            '\n'.join(['route-map rpl1 permit 10', ' match metric 5',
                       ' exit']))

        # import pdb; pdb.set_trace()
        rpl2 = RoutePolicy(policy_definition='rpl2', route_disposition='deny')
        dev2.add_feature(rpl2)

        rpl2.device_attr[dev2].statement_attr['20']
        rpl2.device_attr[dev2].statement_attr['20'].set_metric_type = \
            'internal'
        rpl2.device_attr[dev2].statement_attr['20'].set_ext_community_rt = \
            ['100:100','200:200']
        rpl2.device_attr[dev2].statement_attr['20'].\
            set_ext_community_rt_additive = True

        cfgs = rpl2.build_config(apply=False)
        self.assertCountEqual(cfgs.keys(), [dev2.name])
        self.assertMultiLineEqual(
            str(cfgs[dev2.name]), '\n'.join([
                "route-map rpl2 deny 20",
                " set extcommunity rt ['100:100', '200:200'] additive",
                " set metric-type internal", " exit"
            ]))
Пример #4
0
    def test_basic_cfg(self):

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='iosxe')
        dev2 = Device(testbed=testbed, name='PE2', os='iosxe')

        rpl1 = RoutePolicy(policy_definition='rpl1',
                           route_disposition='permit')
        dev1.add_feature(rpl1)

        rpl1.device_attr[dev1].statement_attr['10']
        rpl1.device_attr[dev1].statement_attr['10'].match_med_eq = 5
        rpl1.device_attr[dev1].statement_attr['10'].description = 'test'
        rpl1.device_attr[dev1].statement_attr['10'].match_nexthop_in = '10'
        rpl1.device_attr[dev1].statement_attr['10'].match_nexthop_in_v6 = '30'
        rpl1.device_attr[dev1].statement_attr['10'].match_local_pref_eq = 40
        rpl1.device_attr[dev1].statement_attr['10'].match_route_type = 'internal'
        rpl1.device_attr[dev1].statement_attr['10'].match_community_list = \
            'community-list1'
        rpl1.device_attr[dev1].statement_attr['10'].match_ext_community_list = \
            'community-list2'
        rpl1.device_attr[dev1].statement_attr['10'].match_as_path_list = \
            '100'
        rpl1.device_attr[dev1].statement_attr['10'].match_level_eq = \
            'level-1-2'
        rpl1.device_attr[dev1].statement_attr['10'].match_interface = \
            'GigabitEthernet3/0/1'
        rpl1.device_attr[dev1].statement_attr['10'].match_prefix_list = \
            'prefixlist1'
        rpl1.device_attr[dev1].statement_attr['10'].match_prefix_list_v6 = \
            'prefixlist1v6'
        rpl1.device_attr[dev1].statement_attr['10'].match_tag_list = \
            'match_tag_list'
        rpl1.device_attr[dev1].statement_attr['10'].set_route_origin = \
            'igp'
        rpl1.device_attr[dev1].statement_attr['10'].set_local_pref = \
            100
        rpl1.device_attr[dev1].statement_attr['10'].set_next_hop = \
            '1.1.1.1'
        rpl1.device_attr[dev1].statement_attr['10'].set_next_hop_v6 = \
            '2001:db8:1::1'
        rpl1.device_attr[dev1].statement_attr['10'].set_next_hop_self = \
            True
        rpl1.device_attr[dev1].statement_attr['10'].set_med = \
            '100'
        rpl1.device_attr[dev1].statement_attr['10'].set_as_path_prepend = \
            '100'
        rpl1.device_attr[dev1].statement_attr['10'].set_as_path_prepend_n = \
            3
        rpl1.device_attr[dev1].statement_attr['10'].set_community = \
            ['100:100', '200:200']
        rpl1.device_attr[dev1].statement_attr['10'].set_community_no_export = \
            True
        rpl1.device_attr[dev1].statement_attr['10'].set_community_no_advertise = \
            True
        rpl1.device_attr[dev1].statement_attr['10'].set_community_additive = \
            True
        rpl1.device_attr[dev1].statement_attr['10'].set_community_delete = \
            'communit_list'
        rpl1.device_attr[dev1].statement_attr['10'].set_ext_community_rt = \
            ['100:10']
        rpl1.device_attr[dev1].statement_attr['10'].set_ext_community_rt_additive = \
            True
        rpl1.device_attr[dev1].statement_attr['10'].set_ext_community_soo = \
            '100:10'
        rpl1.device_attr[dev1].statement_attr['10'].set_ext_community_vpn = \
            '100:10'
        rpl1.device_attr[dev1].statement_attr['10'].set_ext_community_delete = \
            'community_list'
        rpl1.device_attr[dev1].statement_attr['10'].set_level = \
            'level-1'
        rpl1.device_attr[dev1].statement_attr['10'].set_metric_type = \
            'internal'
        rpl1.device_attr[dev1].statement_attr['10'].set_metric = \
            30
        rpl1.device_attr[dev1].statement_attr['10'].set_ospf_metric_type = \
            'type-1'
        rpl1.device_attr[dev1].statement_attr['10'].set_ospf_metric = \
            200
        rpl1.device_attr[dev1].statement_attr['10'].set_tag = \
            111
        rpl1.device_attr[dev1].statement_attr['10'].set_weight = \
            100

        self.maxDiff = None
        cfgs = rpl1.build_config(apply=False)
        self.assertCountEqual(cfgs.keys(), [dev1.name])
        self.assertMultiLineEqual(str(cfgs[dev1.name]), '\n'.join(
            ['route-map rpl1 permit 10',
             ' description test',
             ' match metric 5',
             ' match ip next-hop prefix-list 10',
             ' match ipv6 next-hop prefix-list 30',
             ' match local-preference 40',
             ' match route-type internal',
             ' match community community-list1',
             ' match extcommunity community-list2',
             ' match as-path 100',
             ' match route-type level-1',
             ' match route-type level-2',
             ' match interface GigabitEthernet3/0/1',
             ' match ip address prefix-list prefixlist1',
             ' match ipv6 address prefix-list prefixlist1v6',
             ' match tag list match_tag_list',
             ' set origin igp',
             ' set local-preference 100',
             ' set ip next-hop 1.1.1.1',
             ' set ipv6 next-hop 2001:db8:1::1',
             ' set ip next-hop self',
             ' set metric 100',
             " set community 100:100 200:200 no-export no-advertise additive",
             ' set comm-list communit_list delete',
             " set extcommunity rt 100:10 additive",
             ' set extcommunity soo 100:10',
             ' set extcommunity vpn-distinguisher 100:10',
             ' set extcomm-list community_list delete',
             ' set level level-1',
             ' set metric-type internal',
             ' set metric 30',
             ' set metric-type type-1',
             ' set metric 200',
             ' set tag 111',
             ' set weight 100',
             ' exit'
            ]))

        # import pdb; pdb.set_trace()
        rpl2 = RoutePolicy(policy_definition='rpl2',
                           route_disposition='deny')
        dev2.add_feature(rpl2)

        rpl2.device_attr[dev2].statement_attr['20']
        rpl2.device_attr[dev2].statement_attr['20'].set_metric_type = \
            'internal'

        cfgs = rpl2.build_config(apply=False)
        self.assertCountEqual(cfgs.keys(), [dev2.name])
        self.assertMultiLineEqual(str(cfgs[dev2.name]), '\n'.join(
            ['route-map rpl2 deny 20',
             ' set metric-type internal',
             ' exit'
            ]))

        uncfg1 = rpl1.build_unconfig(apply=False)
        self.assertCountEqual(uncfg1.keys(), [dev1.name])
        self.assertMultiLineEqual(
            str(uncfg1[dev1.name]),
            '\n'.join([
                'no route-map rpl1 permit 10'
            ]))

        partial_uncfg1 = rpl1.build_unconfig(
                            apply=False,
                            attributes={'device_attr':{'*':{'statement_attr':\
                                       {'*':"match_med_eq"}}}})

        self.assertCountEqual(partial_uncfg1.keys(), [dev1.name])
        self.assertMultiLineEqual(
            str(partial_uncfg1[dev1.name]),
            '\n'.join([
                'route-map rpl1 permit 10',
                ' no match metric 5',
                ' exit'
            ]))
Пример #5
0
    def test_init(self):

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='iosxr')
        intf1 = Interface(device=dev1,
                          name='GigabitEthernet0/0/0/1',
                          ipv4='10.1.0.1/24')
        intf2 = Interface(device=dev1,
                          name='GigabitEthernet0/0/0/2',
                          ipv4='10.2.0.1/24')
        dev2 = Device(testbed=testbed, name='PE2', os='iosxr')
        intf3 = Interface(device=dev2,
                          name='GigabitEthernet0/0/0/3',
                          ipv4='10.1.0.2/24')
        intf4 = Interface(device=dev2,
                          name='GigabitEthernet0/0/0/4',
                          ipv4='10.2.0.2/24')
        vrf1 = Vrf(name='vrf1')
        vrf2 = Vrf(name='a')  # must be < 'default'

        with self.assertNoWarnings():

            Genie.testbed = None
            with self.assertRaises(TypeError):
                bgp = Bgp()
            with self.assertRaises(TypeError):
                bgp = Bgp(testbed=testbed)
            Genie.testbed = testbed
            with self.assertRaises(TypeError):
                bgp = Bgp()
            bgp = Bgp(asn=100)
            self.assertIs(bgp.testbed, testbed)
            Genie.testbed = testbed
            bgp = Bgp(asn=100)
            self.assertIs(bgp.testbed, Genie.testbed)
            self.assertIs(bgp.testbed, testbed)

            dev1.add_feature(bgp)

            cfgs = bgp.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineEqual(str(cfgs[dev1.name]), '\n'.join([
                'router bgp 100',
                ' exit',
            ]))

            dev2.add_feature(bgp)

            cfgs = bgp.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name, dev2.name])
            self.assertMultiLineEqual(str(cfgs[dev1.name]), '\n'.join([
                'router bgp 100',
                ' exit',
            ]))
            self.assertMultiLineEqual(str(cfgs[dev2.name]), '\n'.join([
                'router bgp 100',
                ' exit',
            ]))

            ospf1 = Ospf(pid=1)
            isis1 = Isis(pid=1)
            rtepol1 = RoutePolicy(name='rtepol1')
            bgp.redistributes = (
                'connected',
                Redistribution(ospf1, metric=20),
                Redistribution(isis1, route_policy=rtepol1),
            )
            bgp.device_attr[dev1].address_family_attr['ipv4 unicast']
            bgp.device_attr[dev2].address_family_attr['ipv4 unicast']

            cfgs = bgp.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name, dev2.name])
            self.assertMultiLineEqual(
                str(cfgs[dev1.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  redistribute connected',
                    '  redistribute ospf 1 metric 20',
                    '  redistribute isis 1 route-policy rtepol1',
                    '  exit',
                    ' exit',
                ]))
            self.assertMultiLineEqual(
                str(cfgs[dev2.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  redistribute connected',
                    '  redistribute ospf 1 metric 20',
                    '  redistribute isis 1 route-policy rtepol1',
                    '  exit',
                    ' exit',
                ]))

            del bgp.redistributes

            bgp.device_attr[dev1].add_neighbor(intf3.ipv4)
            bgp.device_attr[dev1].neighbor_attr[intf3.ipv4].\
                address_family_attr['ipv4 unicast']
            bgp.device_attr[dev1].add_vrf(vrf1)
            bgp.device_attr[dev1].vrf_attr[vrf1].address_family_attr[
                'ipv4 unicast']
            bgp.device_attr[dev1].vrf_attr[vrf1].add_neighbor(intf4.ipv4)
            bgp.device_attr[dev1].vrf_attr[vrf1].neighbor_attr[intf4.ipv4].\
                address_family_attr['ipv4 unicast']
            bgp.device_attr[dev1].add_vrf(vrf2)
            bgp.device_attr[dev1].vrf_attr[vrf2].address_family_attr[
                'ipv4 unicast']

            cfgs = bgp.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name, dev2.name])
            self.assertMultiLineEqual(
                str(cfgs[dev1.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  exit',
                    ' neighbor 10.1.0.2',
                    '  remote-as 100',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  exit',
                    ' vrf a',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  exit',
                    ' vrf vrf1',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  neighbor 10.2.0.2',
                    '   remote-as 100',
                    '   address-family ipv4 unicast',
                    '    exit',
                    '   exit',
                    '  exit',
                    ' exit',
                ]))
            self.assertMultiLineEqual(
                str(cfgs[dev2.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  exit',
                    ' exit',
                ]))

            cfgs = bgp.build_config(
                apply=False, attributes='device_attr__PE1__vrf_attr__default')
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineEqual(
                str(cfgs[dev1.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  exit',
                    ' neighbor 10.1.0.2',
                    '  remote-as 100',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  exit',
                    ' exit',
                ]))

            cfgs = bgp.build_config(apply=False,
                                    attributes={
                                        'device_attr': {
                                            '*': (),
                                        },
                                    })
            self.assertCountEqual(cfgs.keys(), [dev1.name, dev2.name])
            self.assertMultiLineEqual(str(cfgs[dev1.name]), '\n'.join([
                'router bgp 100',
                ' exit',
            ]))
            self.assertMultiLineEqual(str(cfgs[dev2.name]), '\n'.join([
                'router bgp 100',
                ' exit',
            ]))

            cfgs = bgp.build_config(apply=False,
                                    attributes={
                                        'device_attr': {
                                            'PE1': 'vrf_attr__default',
                                        },
                                    })
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineEqual(
                str(cfgs[dev1.name]), '\n'.join([
                    'router bgp 100',
                    ' address-family ipv4 unicast',
                    '  exit',
                    ' neighbor 10.1.0.2',
                    '  remote-as 100',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  exit',
                    ' exit',
                ]))

            cfgs = bgp.build_config(
                apply=False,
                attributes={
                    'device_attr': {
                        'PE1': 'vrf_attr__default__neighbor_attr__10.1.0.2',
                    },
                })
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineEqual(
                str(cfgs[dev1.name]), '\n'.join([
                    'router bgp 100',
                    ' neighbor 10.1.0.2',
                    '  remote-as 100',
                    '  address-family ipv4 unicast',
                    '   exit',
                    '  exit',
                    ' exit',
                ]))
Пример #6
0
    def test_basic_cfg(self):

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='iosxr')
        dev2 = Device(testbed=testbed, name='PE2', os='iosxr')

        rpl1 = RoutePolicy(policy_definition='rpl1')
        dev1.add_feature(rpl1)

        rpl1.device_attr[dev1].statement_attr[10]
        rpl1.device_attr[dev1].statement_attr[10].match_med_eq = 5
        rpl1.device_attr[dev1].statement_attr[10].match_nexthop_in = 'hop'
        rpl1.device_attr[dev1].statement_attr[10].actions = 'pass'

        rpl1.device_attr[dev1].statement_attr[20]
        rpl1.device_attr[dev1].statement_attr[20].match_med_eq = 10
        rpl1.device_attr[dev1].statement_attr[20].match_nexthop_in = 'hop2'
        rpl1.device_attr[dev1].statement_attr[20].match_local_pref_eq = 16
        rpl1.device_attr[dev1].statement_attr[20].actions = 'drop'

        rpl1.device_attr[dev1].statement_attr[30]
        rpl1.device_attr[dev1].statement_attr[30].match_med_eq = 20
        rpl1.device_attr[dev1].statement_attr[30].match_nexthop_in = 'hop3'
        rpl1.device_attr[dev1].statement_attr[30].actions = 'done'
        rpl1.device_attr[dev1].statement_attr[30].set_med = 32

        cfgs = rpl1.build_config(apply=False)
        self.assertCountEqual(cfgs.keys(), [dev1.name])
        self.assertMultiLineEqual(str(cfgs[dev1.name]), '\n'.join(
            ['route-policy rpl1',
             ' if med eq 5 and next-hop in hop then',
             '  # 10',
             '  pass',
             ' elseif local-preference eq 16 and med eq 10 and next-hop in hop2 then',
             '  # 20',
             '  drop',
             ' elseif med eq 20 and next-hop in hop3 then',
             '  # 30',
             '  set med 32',
             '  done',
             ' endif',
             ' end-policy',
             ' exit'
            ]))

        # Testing the configuration without if/else statements
        # ----------------------------------------------------
        rpl2 = RoutePolicy(policy_definition='rpl2')
        dev2.add_feature(rpl2)

        rpl2.device_attr[dev2].statement_attr['10']
        rpl2.device_attr[dev2].statement_attr['10'].actions = 'pass'
        rpl2.device_attr[dev2].statement_attr['10'].set_med = 32


        cfgs2 = rpl2.build_config(apply=False)
        self.assertCountEqual(cfgs2.keys(), [dev2.name])
        self.assertMultiLineEqual(str(cfgs2[dev2.name]), '\n'.join(
            ['route-policy rpl2',
             ' # 10',
             ' set med 32',
             ' pass',
             ' end-policy',
             ' exit'
            ]))
Пример #7
0
    def test_init(self):

        Genie.testbed = testbed = Testbed()
        dev1 = Device(testbed=testbed, name='PE1', os='iosxr')
        intf1 = Interface(device=dev1, name='GigabitEthernet0/0/0/1',
            ipv4='10.1.0.1/24')
        intf2 = Interface(device=dev1, name='GigabitEthernet0/0/0/2',
            ipv4='10.2.0.1/24')
        intf3 = Interface(device=dev1, name='GigabitEthernet0/0/0/3',
            ipv4='10.3.0.1/24')
        dev2 = Device(testbed=testbed, name='PE2', os='iosxr')
        intf4 = Interface(device=dev2, name='GigabitEthernet0/0/0/3',
            ipv4='10.1.0.2/24')
        intf5 = Interface(device=dev2, name='GigabitEthernet0/0/0/4',
            ipv4='10.2.0.2/24')

        with self.assertNoWarnings():

            rpl1 = RoutePolicy(name='rpl1')
            dev1.add_feature(rpl1)

            rpl1.pass_on = True

            cfgs = rpl1.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineDictEqual(cfgs, {
                dev1.name: '\n'.join([
                    'route-policy rpl1',
                    ' pass',
                    ' end-policy',
                ]),
            })

            rpl1 = RoutePolicy(name='rpl1')
            dev1.add_feature(rpl1)

            rpl1.conditions = []
            cond = RoutePolicy.Condition(
                RoutePolicy.Condition.op_contains,
                (intf1.ipv4.ip, intf2.ipv4.network),
                'destination')
            cond.if_attr.set_nexthop = intf3.ipv4.ip
            cond.else_attr.drop_on = True
            rpl1.conditions.append(cond)

            cfgs = rpl1.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineDictEqual(cfgs, {
                dev1.name: '\n'.join([
                    'route-policy rpl1',
                    ' if destination in (10.1.0.1, 10.2.0.0/24) then',
                    '  set next-hop 10.3.0.1',
                    ' else',
                    '  drop',
                    ' endif',
                    ' end-policy',
                ]),
            })

            class A(object):
                def __repr__(self):
                    return '<a>'
                def __init__(self):
                    self.rpl_set = Mock(side_effect=setattr)
                    self.rpl_get = Mock(side_effect=getattr)

            a = A()
            a.destination = intf5.ipv4.ip
            pass_on = rpl1.rpl_apply_attributes(a, setattr=a.rpl_set,
                getattr=a.rpl_get)
            self.assertEqual(a.rpl_get.call_args_list, [
                unittest.mock.call(a, 'destination'),
            ])
            self.assertEqual(a.rpl_set.call_args_list, [
                unittest.mock.call(a, 'nexthop', intf3.ipv4.ip),
            ])
            self.assertIs(pass_on, True)

            a = A()
            a.destination = intf4.ipv4.ip
            pass_on = rpl1.rpl_apply_attributes(a, setattr=a.rpl_set,
                getattr=a.rpl_get)
            self.assertEqual(a.rpl_get.call_args_list, [
                unittest.mock.call(a, 'destination'),
            ])
            self.assertEqual(a.rpl_set.call_args_list, [
                unittest.mock.call(a, 'drop', True),
            ])
            self.assertIs(pass_on, False)

            del cond.else_attr.drop_on
            cfgs = rpl1.build_config(apply=False)
            self.assertCountEqual(cfgs.keys(), [dev1.name])
            self.assertMultiLineDictEqual(cfgs, {
                dev1.name: '\n'.join([
                    'route-policy rpl1',
                    ' if destination in (10.1.0.1, 10.2.0.0/24) then',
                    '  set next-hop 10.3.0.1',
                    ' endif',
                    ' end-policy',
                ]),
            })

            a = A()
            a.destination = intf4.ipv4.ip
            pass_on = rpl1.rpl_apply_attributes(a, setattr=a.rpl_set,
                getattr=a.rpl_get)
            self.assertEqual(a.rpl_get.call_args_list, [
                unittest.mock.call(a, 'destination'),
            ])
            self.assertEqual(a.rpl_set.call_args_list, [
            ])
            self.assertIs(pass_on, False)