def test_delete_bgpvpn_remaining_plugged_ports_after_update(self):
        dummy_port10 = base.DummyPort(base.NETWORK1,
                                      base.PORT10,
                                      bgpvpn_port=True,
                                      evpn=base.BGPVPN_L2_RT10).__dict__
        dummy_port11 = base.DummyPort(base.NETWORK1,
                                      base.PORT11,
                                      bgpvpn_port=True,
                                      evpn=base.BGPVPN_L2_RT10).__dict__

        update_rts = ({
            k: base.BGPVPN_L2_RT10[k] + base.BGPVPN_L2_RT20[k]
            for k in agent.RT_TYPES
        })

        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l2vpn=update_rts).__dict__

        dummy_bgpvpn1bis = base.DummyBGPVPN(base.NETWORK1,
                                            l2vpn=base.BGPVPN_L2_RT20).__dict__

        with mock.patch.object(self.agent,
                               '_send_attach_local_port') as send_attach_fn:
            expected_calls = [
                self._mock_send_expected_call(agent.BGPVPN_L2,
                                              dummy_port10,
                                              self.DUMMY_VIF10,
                                              others_rts=base.BGPVPN_L2_RT20),
                self._mock_send_expected_call(agent.BGPVPN_L2,
                                              dummy_port11,
                                              self.DUMMY_VIF11,
                                              others_rts=base.BGPVPN_L2_RT20),
                self._mock_send_expected_call(agent.BGPVPN_L2, dummy_port10,
                                              self.DUMMY_VIF10),
                self._mock_send_expected_call(agent.BGPVPN_L2, dummy_port11,
                                              self.DUMMY_VIF11)
            ]

            self.agent.bgpvpn_port_attach(None, dummy_port10)
            self.agent.bgpvpn_port_attach(None, dummy_port11)

            # Verify attachments list consistency
            self._check_network_info(base.NETWORK1['id'], 2,
                                     agent.BGPVPN_SERVICE, agent.BGPVPN_L2,
                                     base.BGPVPN_L2_RT10)

            send_attach_fn.reset_mock()

            self.agent.update_bgpvpn(None, dummy_bgpvpn1)

            self.agent.delete_bgpvpn(None, dummy_bgpvpn1bis)

            send_attach_fn.assert_has_calls(expected_calls, any_order=True)

            # Verify attachments list consistency
            self._check_network_info(base.NETWORK1['id'], 2,
                                     agent.BGPVPN_SERVICE, agent.BGPVPN_L2,
                                     base.BGPVPN_L2_RT10)
    def test_fallback(self):
        GW_MAC = 'aa:bb:cc:dd:ee:ff'

        with mock.patch.object(
                self.agent.int_br,
                'get_vif_port_by_id',
                side_effect=[self.DUMMY_VIF10, self.DUMMY_VIF11]):
            super(TestServiceBGPVPNOVS,
                  self).test_update_bgpvpn_already_plugged_ports()

            port10_with_gw_mac = base.DummyPort(base.NETWORK1,
                                                base.PORT10).__dict__
            port10_with_gw_mac.update({'gateway_mac': GW_MAC})
            port10_with_gw_mac.update(
                base.DummyBGPVPN(base.NETWORK1,
                                 l3vpn=base.BGPVPN_L3_RT100).__dict__)
            with mock.patch.object(self.agent, '_send_attach_local_port') as\
                    send_attach_fn:
                self.agent.bgpvpn_port_attach(None,
                                              copy.copy(port10_with_gw_mac))

                fallback = {
                    'dst_mac': GW_MAC,
                    'ovs_port_number': base.PATCH_MPLS_TO_INT_OFPORT,
                    'src_mac': '00:00:5e:2a:10:00'
                }

                expected_calls = [
                    self._mock_send_expected_call(agent.BGPVPN_L3,
                                                  port10_with_gw_mac,
                                                  self.DUMMY_VIF10,
                                                  fallback=fallback),
                ]

                send_attach_fn.assert_has_calls(expected_calls)
    def test_update_bgpvpn_already_plugged_ports(self):
        dummy_port10 = base.DummyPort(base.NETWORK1, base.PORT10).__dict__
        dummy_port11 = base.DummyPort(base.NETWORK1, base.PORT11).__dict__

        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l3vpn=base.BGPVPN_L3_RT100).__dict__

        with mock.patch.object(self.agent,
                               '_send_attach_local_port') as send_attach_fn:
            expected_calls = [
                self._mock_send_expected_call(agent.IPVPN,
                                              dummy_port10,
                                              self.DUMMY_VIF10,
                                              others_rts=base.BGPVPN_L3_RT100),
                self._mock_send_expected_call(agent.IPVPN,
                                              dummy_port11,
                                              self.DUMMY_VIF11,
                                              others_rts=base.BGPVPN_L3_RT100)
            ]

            self.agent.bgpvpn_port_attach(None, dummy_port10)
            self.agent.bgpvpn_port_attach(None, dummy_port11)

            # Verify attachments list consistency
            self._check_network_info(base.NETWORK1['id'], 2)

            self.agent.update_bgpvpn(None, dummy_bgpvpn1)

            send_attach_fn.assert_has_calls(expected_calls, any_order=True)

            # Verify attachments list consistency
            self._check_network_info(base.NETWORK1['id'], 2,
                                     agent.BGPVPN_SERVICE, agent.BGPVPN_L3,
                                     base.BGPVPN_L3_RT100)
    def test_evpn_no_gateway_arp_voodoo(self):
        GW_MAC = 'aa:bb:cc:dd:ee:ff'

        with mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
                               side_effect=[self.DUMMY_VIF10,
                                            self.DUMMY_VIF11]), \
                mock.patch.object(self.agent.int_br,
                                  'add_flow') as add_flow, \
                mock.patch.object(self.agent.int_br,
                                  'delete_flows') as delete_flows:

            port10_with_gw_mac = base.DummyPort(base.NETWORK1,
                                                base.PORT10).__dict__
            port10_with_gw_mac.update({'gateway_mac': GW_MAC})
            port10_with_gw_mac.update(
                base.DummyBGPVPN(base.NETWORK1,
                                 l2vpn=base.BGPVPN_L2_RT10).__dict__)

            self.agent.bgpvpn_port_attach(None, copy.copy(port10_with_gw_mac))

            self.assertEqual(0, add_flow.call_count)

            self.agent.bgpvpn_port_detach(
                None,
                base.DummyPort(base.NETWORK1, base.PORT10).__dict__)
            self.assertEqual(0, delete_flows.call_count)

            self.agent.bgpvpn_port_detach(
                None,
                base.DummyPort(base.NETWORK1, base.PORT11).__dict__)

            self.assertEqual(0, delete_flows.call_count)
    def test_delete_bgpvpn_no_plugged_ports(self):
        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l2vpn=base.BGPVPN_L2_RT10).__dict__

        with mock.patch.object(self.agent,
                               '_send_detach_local_port') as send_detach_fn:
            self.agent.delete_bgpvpn(None, dummy_bgpvpn1)

            self.assertEqual(0, send_detach_fn.call_count,
                             "Send detach mustn't be called")
    def test_gateway_arp_voodoo_ovs_restart(self):
        GW_MAC = 'aa:bb:cc:dd:ee:ff'

        with mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
                               side_effect=[self.DUMMY_VIF10,
                                            self.DUMMY_VIF11]), \
                mock.patch.object(self.agent.int_br,
                                  'add_flow') as add_flow:
            port10 = base.DummyPort(base.NETWORK1, base.PORT10).__dict__
            port10.update({'gateway_mac': GW_MAC})

            self.agent.bgpvpn_port_attach(None, copy.copy(port10))

            dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                             l3vpn=base.BGPVPN_L3_RT100,
                                             gateway_mac=GW_MAC).__dict__

            self.agent.update_bgpvpn(None, dummy_bgpvpn1)

            self.assertEqual(2, add_flow.call_count)

            expected_calls = [
                mock.call(table=mock.ANY,
                          priority=2,
                          proto='arp',
                          arp_op=0x2,
                          dl_src=GW_MAC,
                          arp_sha=GW_MAC,
                          arp_spa='10.0.0.1',
                          actions="drop"),
                mock.call(table=mock.ANY,
                          priority=2,
                          proto='arp',
                          arp_op=0x01,
                          dl_src=GW_MAC,
                          arp_spa='10.0.0.1',
                          arp_sha=GW_MAC,
                          actions="load:0x0->NXM_OF_ARP_SPA[],NORMAL")
            ]
            add_flow.assert_has_calls(expected_calls)

            add_flow.reset_mock()

            self.agent.ovs_restarted_bgpvpn()

            add_flow.assert_has_calls(expected_calls)
    def test_update_bgpvpn_different_vpn_types(self):
        dummy_port10 = base.DummyPort(base.NETWORK1,
                                      base.PORT10,
                                      bgpvpn_port=True,
                                      evpn=base.BGPVPN_L2_RT10).__dict__

        dummy_port10bis = base.DummyPort(base.NETWORK1,
                                         base.PORT10,
                                         bgpvpn_port=True,
                                         evpn=base.BGPVPN_L2_RT10,
                                         ipvpn=base.BGPVPN_L3_RT100).__dict__

        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l2vpn=base.BGPVPN_L2_RT10,
                                         l3vpn=base.BGPVPN_L3_RT100).__dict__

        with mock.patch.object(self.agent,
                               '_send_attach_local_port') as send_attach_fn:
            expected_calls = [
                self._mock_send_expected_call(agent.BGPVPN_L2, dummy_port10,
                                              self.DUMMY_VIF10),
                self._mock_send_expected_call(agent.BGPVPN_L2, dummy_port10bis,
                                              self.DUMMY_VIF10),
                self._mock_send_expected_call(agent.BGPVPN_L3,
                                              dummy_port10bis,
                                              self.DUMMY_VIF10,
                                              evpn2ipvpn=True)
            ]

            self.agent.bgpvpn_port_attach(None, dummy_port10)

            self.agent.update_bgpvpn(None, dummy_bgpvpn1)

            send_attach_fn.assert_has_calls(expected_calls)

            for bgpvpn_type, bgpvpn_rts in [
                (agent.BGPVPN_L2, base.BGPVPN_L2_RT10),
                (agent.BGPVPN_L3, base.BGPVPN_L3_RT100)
            ]:
                self._check_network_info(base.NETWORK1['id'], 1,
                                         agent.BGPVPN_SERVICE, bgpvpn_type,
                                         bgpvpn_rts)
    def test_delete_bgpvpn_had_plugged_ports(self):
        dummy_port10 = base.DummyPort(base.NETWORK1,
                                      base.PORT10,
                                      bgpvpn_port=True,
                                      ipvpn=base.BGPVPN_L2_RT10).__dict__
        dummy_detach10 = dict(id=base.PORT10['id'],
                              network_id=base.NETWORK1['id'])

        dummy_port11 = base.DummyPort(base.NETWORK1,
                                      base.PORT11,
                                      bgpvpn_port=True,
                                      ipvpn=base.BGPVPN_L2_RT10).__dict__
        dummy_detach11 = dict(id=base.PORT11['id'],
                              network_id=base.NETWORK1['id'])

        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l3vpn=base.BGPVPN_L2_RT10).__dict__

        with mock.patch.object(self.agent,
                               '_send_detach_local_port') as send_detach_fn:

            self.agent.bgpvpn_port_attach(None, dummy_port10)
            self.agent.bgpvpn_port_attach(None, dummy_port11)

            self.agent.bgpvpn_port_detach(None, dummy_detach10)
            self.agent.bgpvpn_port_detach(None, dummy_detach11)

            self.assertEqual(2, send_detach_fn.call_count,
                             "Send detach must be called twice")

            self.assertEqual(
                0, len(self.agent.networks_info),
                "Registered attachments list must be empty: %s" %
                self.agent.networks_info)

            send_detach_fn.reset_mock()
            self.agent.delete_bgpvpn(None, dummy_bgpvpn1)

            self.assertEqual(0, send_detach_fn.call_count,
                             "Send detach isn't be called")
    def test_update_bgpvpn_same_vpn_types(self):
        dummy_port10 = base.DummyPort(base.NETWORK1,
                                      base.PORT10,
                                      bgpvpn_port=True,
                                      evpn=base.BGPVPN_L2_RT10).__dict__

        dummy_port10bis = base.DummyPort(base.NETWORK1,
                                         base.PORT10,
                                         bgpvpn_port=True,
                                         evpn=base.BGPVPN_L2_RT20).__dict__

        evpn_rts = ({
            k: base.BGPVPN_L2_RT10[k] + base.BGPVPN_L2_RT20[k]
            for k in agent.RT_TYPES
        })

        dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                         l2vpn=evpn_rts).__dict__

        with mock.patch.object(self.agent,
                               '_send_attach_local_port') as send_attach_fn:
            expected_calls = [
                self._mock_send_expected_call(agent.BGPVPN_L2, dummy_port10,
                                              self.DUMMY_VIF10),
                self._mock_send_expected_call(agent.BGPVPN_L2,
                                              dummy_port10bis,
                                              self.DUMMY_VIF10,
                                              others_rts=base.BGPVPN_L2_RT10)
            ]

            self.agent.bgpvpn_port_attach(None, dummy_port10)

            self.agent.update_bgpvpn(None, dummy_bgpvpn1)

            send_attach_fn.assert_has_calls(expected_calls)

            self._check_network_info(base.NETWORK1['id'], 1,
                                     agent.BGPVPN_SERVICE, agent.BGPVPN_L2,
                                     evpn_rts)
    def test_gateway_plug_before_update(self):
        GW_MAC = 'aa:bb:cc:dd:ee:ff'

        with mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
                               side_effect=[self.DUMMY_VIF10]), \
                mock.patch.object(self.agent.int_br,
                                  'add_flow') as add_flow:
            port10 = base.DummyPort(base.NETWORK1, base.PORT10).__dict__

            self.agent.bgpvpn_port_attach(None, copy.copy(port10))

            dummy_bgpvpn1 = base.DummyBGPVPN(base.NETWORK1,
                                             l3vpn=base.BGPVPN_L3_RT100,
                                             gateway_mac=GW_MAC).__dict__

            with mock.patch.object(self.agent, '_send_attach_local_port') as\
                    send_attach_fn:

                self.agent.update_bgpvpn(None, copy.copy(dummy_bgpvpn1))

                self.assertEqual(2, add_flow.call_count)

                add_flow.assert_has_calls([
                    mock.call(table=mock.ANY,
                              priority=2,
                              proto='arp',
                              arp_op=0x2,
                              dl_src=GW_MAC,
                              arp_sha=GW_MAC,
                              arp_spa='10.0.0.1',
                              actions="drop"),
                    mock.call(table=mock.ANY,
                              priority=2,
                              proto='arp',
                              arp_op=0x01,
                              dl_src=GW_MAC,
                              arp_spa='10.0.0.1',
                              arp_sha=GW_MAC,
                              actions="load:0x0->NXM_OF_ARP_SPA[],NORMAL")
                ])

                fallback = {
                    'dst_mac': GW_MAC,
                    'ovs_port_number': base.PATCH_MPLS_TO_INT_OFPORT,
                    'src_mac': '00:00:5e:2a:10:00'
                }

                expected_calls = [
                    self._mock_send_expected_call(
                        agent.IPVPN,
                        port10,
                        self.DUMMY_VIF10,
                        others_rts=base.BGPVPN_L3_RT100,
                        fallback=fallback),
                ]

                send_attach_fn.assert_has_calls(expected_calls)

                self.agent.delete_bgpvpn(None, copy.copy(dummy_bgpvpn1))

                add_flow.reset_mock()
                self.assertEqual(0, add_flow.call_count)

                self.agent.update_bgpvpn(None, dummy_bgpvpn1)

                self.assertEqual(2, add_flow.call_count)
    def test_gateway_arp_voodoo(self):
        GW_MAC = 'aa:bb:cc:dd:ee:ff'

        with mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
                               side_effect=[self.DUMMY_VIF10,
                                            self.DUMMY_VIF11]), \
                mock.patch.object(self.agent.int_br,
                                  'add_flow') as add_flow, \
                mock.patch.object(self.agent.tun_br,
                                  'delete_flows') as tun_delete_flows,\
                mock.patch.object(self.agent.int_br,
                                  'delete_flows') as int_delete_flows:
            super(TestServiceBGPVPNOVS,
                  self).test_update_bgpvpn_already_plugged_ports()

            port10_with_gw_mac = base.DummyPort(base.NETWORK1,
                                                base.PORT10).__dict__
            port10_with_gw_mac.update({'gateway_mac': GW_MAC})
            port10_with_gw_mac.update(
                base.DummyBGPVPN(base.NETWORK1,
                                 l3vpn=base.BGPVPN_L3_RT100).__dict__)

            self.agent.bgpvpn_port_attach(None, copy.copy(port10_with_gw_mac))

            self.assertEqual(2, add_flow.call_count)

            add_flow.assert_has_calls([
                mock.call(table=mock.ANY,
                          priority=2,
                          proto='arp',
                          arp_op=0x2,
                          dl_src=GW_MAC,
                          arp_sha=GW_MAC,
                          arp_spa='10.0.0.1',
                          actions="drop"),
                mock.call(table=mock.ANY,
                          priority=2,
                          proto='arp',
                          arp_op=0x01,
                          dl_src=GW_MAC,
                          arp_spa='10.0.0.1',
                          arp_sha=GW_MAC,
                          actions="load:0x0->NXM_OF_ARP_SPA[],NORMAL")
            ])

            self.agent.bgpvpn_port_detach(
                None,
                base.DummyPort(base.NETWORK1, base.PORT10).__dict__)

            self.assertEqual(0, tun_delete_flows.call_count)
            self.assertEqual(0, int_delete_flows.call_count)

            self.agent.bgpvpn_port_detach(
                None,
                base.DummyPort(base.NETWORK1, base.PORT11).__dict__)

            self.assertEqual(1, tun_delete_flows.call_count)
            self.assertEqual(1, int_delete_flows.call_count)

            tun_delete_flows.assert_has_calls([
                mock.call(
                    table=mock.ANY,
                    priority=2,
                    strict=True,
                    proto='arp',
                    arp_op=0x01,
                    arp_tpa='10.0.0.1',
                    dl_vlan=mock.ANY,
                )
            ])
            int_delete_flows.assert_has_calls([
                mock.call(table=mock.ANY,
                          proto='arp',
                          dl_src=GW_MAC,
                          arp_sha=GW_MAC),
            ])