]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Refactor l2_pop code to pass mac/ip info more readably
authorCarl Baldwin <carl.baldwin@hp.com>
Wed, 6 Aug 2014 01:02:09 +0000 (01:02 +0000)
committerCarl Baldwin <carl.baldwin@hp.com>
Wed, 15 Oct 2014 22:17:33 +0000 (22:17 +0000)
Previous code used a 2 element array to represent a mac/ip address
pair.  Code assumed that element 0 was mac and 1 was ip.  This made
the code difficult to read and difficult to maintain.  An attempt was
made to insert a third value that failed miserably because of the
position dependence and other code that assumed not only positions but
also the number of elements.

Using a namedtuple seems to be the best way to get better
maintainability.  Named tuples can be compared with regular tuples.
The json serializer still uses an array to represent it so the on-wire
representation of the object has not changed.  A short snip of code
was required to restore the namedtuple from the RPC message.

Change-Id: I7f8c93b0e12ee0179bb23dfbb3a3d814615b1c2e
Closes-Bug: #1352801

neutron/agent/l2population_rpc.py
neutron/common/constants.py
neutron/plugins/ml2/drivers/l2pop/mech_driver.py
neutron/plugins/ml2/drivers/l2pop/rpc.py
neutron/plugins/ofagent/agent/ofa_neutron_agent.py
neutron/plugins/openvswitch/agent/ovs_neutron_agent.py
neutron/tests/unit/agent/l2population_rpc_base.py
neutron/tests/unit/agent/test_l2population_rpc.py
neutron/tests/unit/ml2/drivers/test_l2population.py
neutron/tests/unit/ofagent/test_ofa_neutron_agent.py
neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py

index 2798eee5e7898c238130dc7e0fceb7ac13f2e761..6cc64fc689b099c402e9e2928cd77ed5a55f51be 100644 (file)
@@ -21,6 +21,7 @@ import six
 from neutron.common import constants as n_const
 from neutron.common import log
 from neutron.openstack.common import log as logging
+from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
 
 LOG = logging.getLogger(__name__)
 
@@ -38,17 +39,43 @@ class L2populationRpcCallBackMixin(object):
     @log.log
     def add_fdb_entries(self, context, fdb_entries, host=None):
         if not host or host == cfg.CONF.host:
-            self.fdb_add(context, fdb_entries)
+            self.fdb_add(context, self._unmarshall_fdb_entries(fdb_entries))
 
     @log.log
     def remove_fdb_entries(self, context, fdb_entries, host=None):
         if not host or host == cfg.CONF.host:
-            self.fdb_remove(context, fdb_entries)
+            self.fdb_remove(context, self._unmarshall_fdb_entries(fdb_entries))
 
     @log.log
     def update_fdb_entries(self, context, fdb_entries, host=None):
         if not host or host == cfg.CONF.host:
-            self.fdb_update(context, fdb_entries)
+            self.fdb_update(context, self._unmarshall_fdb_entries(fdb_entries))
+
+    @staticmethod
+    def _unmarshall_fdb_entries(fdb_entries):
+        """Prepares fdb_entries from JSON.
+
+        All methods in this class that receive messages should call this to
+        unmarshall fdb_entries from the wire.
+
+        :param fdb_entries: Original fdb_entries data-structure.  Looks like:
+            {
+                <uuid>: {
+                    ...,
+                    'ports': {
+                        <ip address>: [ [<mac>, <ip>], ...  ],
+                        ...
+
+        :returns: Deep copy with [<mac>, <ip>] converted to PortInfo
+        """
+        unmarshalled = dict(fdb_entries)
+        for value in unmarshalled.values():
+            if 'ports' in value:
+                value['ports'] = dict(
+                    (address, [l2pop_rpc.PortInfo(*pi) for pi in port_infos])
+                    for address, port_infos in value['ports'].items()
+                )
+        return unmarshalled
 
     @abc.abstractmethod
     def fdb_add(self, context, fdb_entries):
@@ -80,9 +107,10 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin):
 
         :param br: represent the bridge on which add_fdb_flow should be
         applied.
-        :param port_info: list to include mac and ip.
+        :param port_info: PortInfo instance to include mac and ip.
+            .mac_address
+            .ip_address
 
-            [mac, ip]
         :remote_ip: remote ip address.
         :param lvm: a local VLAN map of network.
         :param ofport: a port to add.
@@ -100,8 +128,10 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin):
 
         :param br: represent the bridge on which del_fdb_flow should be
         applied.
-        :param port_info: a list to contain mac and ip.
-            [mac, ip]
+        :param port_info: PortInfo instance to include mac and ip.
+            .mac_address
+            .ip_address
+
         :remote_ip: remote ip address.
         :param lvm: local VLAN map of network.
         :param ofport: a port to delete.
@@ -222,13 +252,16 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin):
                             agent and network.
                                {'net1':
                                 {'agent_ip':
-                                 {'before': [[mac, ip]],
-                                  'after': [[mac, ip]]
+                                 {'before': PortInfo,
+                                  'after': PortInfo
                                  }
                                 }
                                 'net2':
                                 ...
                                }
+
+                             PortInfo has .mac_address and .ip_address attrs.
+
         :param local_ip: local IP address of this agent.
         :local_vlan_map: local VLAN map of network.
         '''
@@ -243,11 +276,13 @@ class L2populationRpcCallBackTunnelMixin(L2populationRpcCallBackMixin):
                     continue
 
                 after = state.get('after', [])
-                for mac, ip in after:
-                    self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, mac,
-                                                   ip)
+                for mac_ip in after:
+                    self.setup_entry_for_arp_reply(br, 'add', lvm.vlan,
+                                                   mac_ip.mac_address,
+                                                   mac_ip.ip_address)
 
                 before = state.get('before', [])
-                for mac, ip in before:
-                    self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan, mac,
-                                                   ip)
+                for mac_ip in before:
+                    self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan,
+                                                   mac_ip.mac_address,
+                                                   mac_ip.ip_address)
index 59066903b11366300e388ea9f893cbe94d02ba31..2935760c605c62a2dcfeabea7605af9908236888 100644 (file)
@@ -70,7 +70,7 @@ MAX_GRE_ID = 2 ** 32 - 1
 MIN_VXLAN_VNI = 1
 MAX_VXLAN_VNI = 2 ** 24 - 1
 
-FLOODING_ENTRY = ['00:00:00:00:00:00', '0.0.0.0']
+FLOODING_ENTRY = ('00:00:00:00:00:00', '0.0.0.0')
 
 EXT_NS_COMP = '_backward_comp_e_ns'
 EXT_NS = '_extension_ns'
index c85acb1c73f0b9a3be9a80bba7166f0ed9121e7b..75c8f0d063a67ef023552d720bab7ce48b6b8a8d 100644 (file)
@@ -40,8 +40,9 @@ class L2populationMechanismDriver(api.MechanismDriver,
         self.migrated_ports = {}
 
     def _get_port_fdb_entries(self, port):
-        return [[port['mac_address'],
-                 ip['ip_address']] for ip in port['fixed_ips']]
+        return [l2pop_rpc.PortInfo(mac_address=port['mac_address'],
+                                   ip_address=ip['ip_address'])
+                for ip in port['fixed_ips']]
 
     def delete_port_postcommit(self, context):
         port = context.current
@@ -75,8 +76,12 @@ class L2populationMechanismDriver(api.MechanismDriver,
             return
         agent, agent_host, agent_ip, segment, port_fdb_entries = port_infos
 
-        orig_mac_ip = [[port['mac_address'], ip] for ip in orig_ips]
-        port_mac_ip = [[port['mac_address'], ip] for ip in port_ips]
+        orig_mac_ip = [l2pop_rpc.PortInfo(mac_address=port['mac_address'],
+                                          ip_address=ip)
+                       for ip in orig_ips]
+        port_mac_ip = [l2pop_rpc.PortInfo(mac_address=port['mac_address'],
+                                          ip_address=ip)
+                       for ip in port_ips]
 
         upd_fdb_entries = {port['network_id']: {agent_ip: {}}}
 
index 8b5efacf292804addb0bb49576914d24016937b9..95341cca5010980ca5a9603bf62cf004838d68c2 100644 (file)
@@ -13,6 +13,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import collections
+import copy
+
 from neutron.common import rpc as n_rpc
 from neutron.common import topics
 from neutron.openstack.common import log as logging
@@ -21,6 +24,9 @@ from neutron.openstack.common import log as logging
 LOG = logging.getLogger(__name__)
 
 
+PortInfo = collections.namedtuple("PortInfo", "mac_address ip_address")
+
+
 class L2populationAgentNotifyAPI(n_rpc.RpcProxy):
     BASE_RPC_API_VERSION = '1.0'
 
@@ -39,8 +45,10 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy):
                    'method': method,
                    'fdb_entries': fdb_entries})
 
+        marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries)
         self.fanout_cast(context,
-                         self.make_msg(method, fdb_entries=fdb_entries),
+                         self.make_msg(method,
+                                       fdb_entries=marshalled_fdb_entries),
                          topic=self.topic_l2pop_update)
 
     def _notification_host(self, context, method, fdb_entries, host):
@@ -50,8 +58,10 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy):
                    'topic': self.topic,
                    'method': method,
                    'fdb_entries': fdb_entries})
+        marshalled_fdb_entries = self._marshall_fdb_entries(fdb_entries)
         self.cast(context,
-                  self.make_msg(method, fdb_entries=fdb_entries),
+                  self.make_msg(method,
+                                fdb_entries=marshalled_fdb_entries),
                   topic='%s.%s' % (self.topic_l2pop_update, host))
 
     def add_fdb_entries(self, context, fdb_entries, host=None):
@@ -80,3 +90,28 @@ class L2populationAgentNotifyAPI(n_rpc.RpcProxy):
             else:
                 self._notification_fanout(context, 'update_fdb_entries',
                                           fdb_entries)
+
+    @staticmethod
+    def _marshall_fdb_entries(fdb_entries):
+        """Prepares fdb_entries for serialization to JSON for RPC.
+
+        All methods in this class that send messages should call this to
+        marshall fdb_entries for the wire.
+
+        :param fdb_entries: Original fdb_entries data-structure.  Looks like:
+            {
+                <uuid>: {
+                    ...,
+                    'ports': {
+                        <ip address>: [ PortInfo, ...  ],
+                        ...
+
+        :returns: Deep copy with PortInfo converted to [mac, ip]
+        """
+        marshalled = copy.deepcopy(fdb_entries)
+        for value in marshalled.values():
+            if 'ports' in value:
+                for address, port_infos in value['ports'].items():
+                    value['ports'][address] = [[mac, ip]
+                                               for mac, ip in port_infos]
+        return marshalled
index 8c4b98a3e3132c3cf40f14fff93f01861c3bf0ba..76f692891fd6a142f50029f00e7cad5fd5ffbf49 100644 (file)
@@ -379,8 +379,9 @@ class OFANeutronAgent(n_rpc.RpcCallback,
             for port_info in port_infos:
                 if port_info == n_const.FLOODING_ENTRY:
                     continue
-                self.ryuapp.add_arp_table_entry(
-                    lvm.vlan, port_info[1], port_info[0])
+                self.ryuapp.add_arp_table_entry(lvm.vlan,
+                                                port_info.ip_address,
+                                                port_info.mac_address)
 
     @log.log
     def _fdb_remove_arp(self, lvm, agent_ports):
@@ -388,7 +389,7 @@ class OFANeutronAgent(n_rpc.RpcCallback,
             for port_info in port_infos:
                 if port_info == n_const.FLOODING_ENTRY:
                     continue
-                self.ryuapp.del_arp_table_entry(lvm.vlan, port_info[1])
+                self.ryuapp.del_arp_table_entry(lvm.vlan, port_info.ip_address)
 
     def add_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
         if port_info == n_const.FLOODING_ENTRY:
@@ -399,11 +400,13 @@ class OFANeutronAgent(n_rpc.RpcCallback,
                 lvm.tun_ofports, goto_next=True)
         else:
             self.ryuapp.add_arp_table_entry(
-                lvm.vlan, port_info[1], port_info[0])
+                lvm.vlan,
+                port_info.ip_address,
+                port_info.mac_address)
             br.install_tunnel_output(
                 tables.TUNNEL_OUT,
                 lvm.vlan, lvm.segmentation_id,
-                set([ofport]), goto_next=False, eth_dst=port_info[0])
+                set([ofport]), goto_next=False, eth_dst=port_info.mac_address)
 
     def del_fdb_flow(self, br, port_info, remote_ip, lvm, ofport):
         if port_info == n_const.FLOODING_ENTRY:
@@ -418,9 +421,9 @@ class OFANeutronAgent(n_rpc.RpcCallback,
                     tables.TUNNEL_FLOOD[lvm.network_type],
                     lvm.vlan)
         else:
-            self.ryuapp.del_arp_table_entry(lvm.vlan, port_info[1])
+            self.ryuapp.del_arp_table_entry(lvm.vlan, port_info.ip_address)
             br.delete_tunnel_output(tables.TUNNEL_OUT,
-                                    lvm.vlan, eth_dst=port_info[0])
+                                    lvm.vlan, eth_dst=port_info.mac_address)
 
     def setup_entry_for_arp_reply(self, br, action, local_vid, mac_address,
                                   ip_address):
index 8901cdeb9b233ee917779df4e33f600615cf5875..173ba01bddaf21f773cc0dd25d6bc5b93a578b38 100644 (file)
@@ -375,12 +375,13 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
                         actions="strip_vlan,set_tunnel:%s,output:%s" %
                         (lvm.segmentation_id, ofports))
         else:
-            self.setup_entry_for_arp_reply(br, 'add', lvm.vlan, port_info[0],
-                                           port_info[1])
+            self.setup_entry_for_arp_reply(br, 'add', lvm.vlan,
+                                           port_info.mac_address,
+                                           port_info.ip_address)
             br.add_flow(table=constants.UCAST_TO_TUN,
                         priority=2,
                         dl_vlan=lvm.vlan,
-                        dl_dst=port_info[0],
+                        dl_dst=port_info.mac_address,
                         actions="strip_vlan,set_tunnel:%s,output:%s" %
                         (lvm.segmentation_id, ofport))
 
@@ -398,10 +399,11 @@ class OVSNeutronAgent(n_rpc.RpcCallback,
                 br.delete_flows(table=constants.FLOOD_TO_TUN, dl_vlan=lvm.vlan)
         else:
             self.setup_entry_for_arp_reply(br, 'remove', lvm.vlan,
-                                           port_info[0], port_info[1])
+                                           port_info.mac_address,
+                                           port_info.ip_address)
             br.delete_flows(table=constants.UCAST_TO_TUN,
                             dl_vlan=lvm.vlan,
-                            dl_dst=port_info[0])
+                            dl_dst=port_info.mac_address)
 
     def _fdb_chg_ip(self, context, fdb_entries):
         LOG.debug("update chg_ip received")
index c9c22de0fff16b3822957fc11d7b59ef98612eb0..8ce6482130312244157bb411dad1352a9881add6 100644 (file)
@@ -18,6 +18,7 @@ import collections
 import mock
 
 from neutron.agent import l2population_rpc
+from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
 from neutron.plugins.openvswitch.agent import ovs_neutron_agent
 from neutron.tests import base
 
@@ -81,9 +82,9 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase):
                          port='port3')]
 
         self.agent_ports = {
-            self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]],
-            self.ports[1].ip: [[self.lvms[1].mac, self.lvms[1].ip]],
-            self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]],
+            self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)],
+            self.ports[1].ip: [(self.lvms[1].mac, self.lvms[1].ip)],
+            self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)],
         }
 
         self.fdb_entries1 = {
@@ -92,21 +93,21 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase):
                 'segment_id': self.lvms[0].segid,
                 'ports': {
                     self.local_ip: [],
-                    self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]]},
+                    self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)]},
             },
             self.lvms[1].net: {
                 'network_type': self.type_gre,
                 'segment_id': self.lvms[1].segid,
                 'ports': {
                     self.local_ip: [],
-                    self.ports[1].ip: [[self.lvms[1].mac, self.lvms[1].ip]]},
+                    self.ports[1].ip: [(self.lvms[1].mac, self.lvms[1].ip)]},
             },
             self.lvms[2].net: {
                 'network_type': self.type_gre,
                 'segment_id': self.lvms[2].segid,
                 'ports': {
                     self.local_ip: [],
-                    self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]]},
+                    self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)]},
             },
         }
 
@@ -129,18 +130,24 @@ class TestL2populationRpcCallBackTunnelMixinBase(base.BaseTestCase):
         self.upd_fdb_entry1_val = {
             self.lvms[0].net: {
                 self.ports[0].ip: {
-                    'before': [[self.lvms[0].mac, self.lvms[0].ip]],
-                    'after': [[self.lvms[1].mac, self.lvms[1].ip]],
+                    'before': [l2pop_rpc.PortInfo(self.lvms[0].mac,
+                               self.lvms[0].ip)],
+                    'after': [l2pop_rpc.PortInfo(self.lvms[1].mac,
+                              self.lvms[1].ip)],
                 },
                 self.ports[1].ip: {
-                    'before': [[self.lvms[0].mac, self.lvms[0].ip]],
-                    'after': [[self.lvms[1].mac, self.lvms[1].ip]],
+                    'before': [l2pop_rpc.PortInfo(self.lvms[0].mac,
+                               self.lvms[0].ip)],
+                    'after': [l2pop_rpc.PortInfo(self.lvms[1].mac,
+                              self.lvms[1].ip)],
                 },
             },
             self.lvms[1].net: {
                 self.ports[2].ip: {
-                    'before': [[self.lvms[0].mac, self.lvms[0].ip]],
-                    'after': [[self.lvms[2].mac, self.lvms[2].ip]],
+                    'before': [l2pop_rpc.PortInfo(self.lvms[0].mac,
+                               self.lvms[0].ip)],
+                    'after': [l2pop_rpc.PortInfo(self.lvms[2].mac,
+                              self.lvms[2].ip)],
                 },
             },
         }
index 563c53b19db4a4cf3bdc77cf0df2bacd4ed2cdde..b0b8f7e49019fda76987367a5318f67379180315 100644 (file)
@@ -39,10 +39,10 @@ class TestL2populationRpcCallBackTunnelMixin(
             results[lvm] = agent_ports
         expected = {
             self.lvm1: {
-                self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]],
+                self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)],
                 self.local_ip: []},
             self.lvm3: {
-                self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]],
+                self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)],
                 self.local_ip: []},
         }
         self.assertEqual(expected, results)
@@ -55,11 +55,11 @@ class TestL2populationRpcCallBackTunnelMixin(
             results[lvm] = agent_ports
         expected = {
             self.lvm1: {
-                self.ports[0].ip: [[self.lvms[0].mac, self.lvms[0].ip]],
+                self.ports[0].ip: [(self.lvms[0].mac, self.lvms[0].ip)],
                 self.local_ip: []},
             self.lvm2: {},
             self.lvm3: {
-                self.ports[2].ip: [[self.lvms[2].mac, self.lvms[2].ip]],
+                self.ports[2].ip: [(self.lvms[2].mac, self.lvms[2].ip)],
                 self.local_ip: []},
         }
         self.assertEqual(expected, results)
@@ -72,11 +72,11 @@ class TestL2populationRpcCallBackTunnelMixin(
             self.fakeagent.fdb_add_tun('context', self.fakebr, self.lvm1,
                                        self.agent_ports, self.ofports)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
-            mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip],
+            mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip),
                       self.ports[1].ip, self.lvm1, self.ports[1].ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -95,11 +95,11 @@ class TestL2populationRpcCallBackTunnelMixin(
         mock_setup_tunnel_port.assert_called_once_with(
             self.fakebr, self.ports[1].ip, self.lvm1.network_type)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
-            mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip],
+            mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip),
                       self.ports[1].ip, self.lvm1, ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -117,9 +117,9 @@ class TestL2populationRpcCallBackTunnelMixin(
         mock_setup_tunnel_port.assert_called_once_with(
             self.fakebr, self.ports[1].ip, self.lvm1.network_type)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -131,11 +131,11 @@ class TestL2populationRpcCallBackTunnelMixin(
             self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1,
                                           self.agent_ports, self.ofports)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
-            mock.call(self.fakebr, [self.lvms[1].mac, self.lvms[1].ip],
+            mock.call(self.fakebr, (self.lvms[1].mac, self.lvms[1].ip),
                       self.ports[1].ip, self.lvm1, self.ports[1].ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -150,12 +150,12 @@ class TestL2populationRpcCallBackTunnelMixin(
             self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1,
                                           self.agent_ports, self.ofports)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
             mock.call(self.fakebr,
-                      [n_const.FLOODING_ENTRY[0], n_const.FLOODING_ENTRY[1]],
+                      (n_const.FLOODING_ENTRY[0], n_const.FLOODING_ENTRY[1]),
                       self.ports[1].ip, self.lvm1, self.ports[1].ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -170,9 +170,9 @@ class TestL2populationRpcCallBackTunnelMixin(
             self.fakeagent.fdb_remove_tun('context', self.fakebr, self.lvm1,
                                           self.agent_ports, self.ofports)
         expected = [
-            mock.call(self.fakebr, [self.lvms[0].mac, self.lvms[0].ip],
+            mock.call(self.fakebr, (self.lvms[0].mac, self.lvms[0].ip),
                       self.ports[0].ip, self.lvm1, self.ports[0].ofport),
-            mock.call(self.fakebr, [self.lvms[2].mac, self.lvms[2].ip],
+            mock.call(self.fakebr, (self.lvms[2].mac, self.lvms[2].ip),
                       self.ports[2].ip, self.lvm1, self.ports[2].ofport),
         ]
         self.assertEqual(sorted(expected),
@@ -223,8 +223,8 @@ class TestL2populationRpcCallBackTunnelMixin(
         upd_fdb_entry_val = {
             self.lvms[0].net: {
                 self.local_ip: {
-                    'before': [[self.lvms[0].mac, self.lvms[0].ip]],
-                    'after': [[self.lvms[1].mac, self.lvms[1].ip]],
+                    'before': [(self.lvms[0].mac, self.lvms[0].ip)],
+                    'after': [(self.lvms[1].mac, self.lvms[1].ip)],
                 },
             },
         }
index 85d8b37a7315fe8950a21599416e261d8abfde5a..1073a0e488f9e6bc5806fa60ad62f29ed31078ca 100644 (file)
@@ -16,6 +16,7 @@
 import contextlib
 import mock
 
+from neutron.agent import l2population_rpc
 from neutron.common import constants
 from neutron.common import topics
 from neutron import context
@@ -26,6 +27,7 @@ from neutron import manager
 from neutron.openstack.common import timeutils
 from neutron.plugins.ml2 import config as config
 from neutron.plugins.ml2.drivers.l2pop import mech_driver as l2pop_mech_driver
+from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
 from neutron.plugins.ml2 import managers
 from neutron.plugins.ml2 import rpc
 from neutron.tests.unit import test_db_plugin as test_plugin
@@ -92,6 +94,8 @@ PLUGIN_NAME = 'neutron.plugins.ml2.plugin.Ml2Plugin'
 NOTIFIER = 'neutron.plugins.ml2.rpc.AgentNotifierApi'
 DEVICE_OWNER_COMPUTE = 'compute:None'
 
+FLOODING_ENTRY_AS_LIST = list(constants.FLOODING_ENTRY)
+
 
 class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
 
@@ -167,6 +171,48 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                               agent_state={'agent_state': L2_AGENT_5},
                               time=timeutils.strtime())
 
+    def test_port_info_compare(self):
+        # An assumption the code makes is that PortInfo compares equal to
+        # equivalent regular tuples.
+        self.assertEqual(("mac", "ip"), l2pop_rpc.PortInfo("mac", "ip"))
+
+        flooding_entry = l2pop_rpc.PortInfo(*constants.FLOODING_ENTRY)
+        self.assertEqual(constants.FLOODING_ENTRY, flooding_entry)
+
+    def test__unmarshall_fdb_entries(self):
+        entries = {'foouuid': {
+            'segment_id': 1001,
+            'ports': {'192.168.0.10': [['00:00:00:00:00:00', '0.0.0.0'],
+                                       ['fa:16:3e:ff:8c:0f', '10.0.0.6']]},
+            'network_type': 'vxlan'}}
+
+        mixin = l2population_rpc.L2populationRpcCallBackMixin
+        entries = mixin._unmarshall_fdb_entries(entries)
+
+        port_info_list = entries['foouuid']['ports']['192.168.0.10']
+        # Check that the lists have been properly converted to PortInfo
+        self.assertIsInstance(port_info_list[0], l2pop_rpc.PortInfo)
+        self.assertIsInstance(port_info_list[1], l2pop_rpc.PortInfo)
+        self.assertEqual(('00:00:00:00:00:00', '0.0.0.0'), port_info_list[0])
+        self.assertEqual(('fa:16:3e:ff:8c:0f', '10.0.0.6'), port_info_list[1])
+
+    def test__marshall_fdb_entries(self):
+        entries = {'foouuid': {
+            'segment_id': 1001,
+            'ports': {'192.168.0.10': [('00:00:00:00:00:00', '0.0.0.0'),
+                                       ('fa:16:3e:ff:8c:0f', '10.0.0.6')]},
+            'network_type': 'vxlan'}}
+
+        entries = l2pop_rpc.L2populationAgentNotifyAPI._marshall_fdb_entries(
+            entries)
+
+        port_info_list = entries['foouuid']['ports']['192.168.0.10']
+        # Check that the PortInfo tuples have been converted to list
+        self.assertIsInstance(port_info_list[0], list)
+        self.assertIsInstance(port_info_list[1], list)
+        self.assertEqual(['00:00:00:00:00:00', '0.0.0.0'], port_info_list[0])
+        self.assertEqual(['fa:16:3e:ff:8c:0f', '10.0.0.6'], port_info_list[1])
+
     def test_fdb_add_called(self):
         self._register_ml2_agents()
 
@@ -193,7 +239,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 {'fdb_entries':
                                  {p1['network_id']:
                                   {'ports':
-                                   {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                   {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                                  [p1['mac_address'],
                                                   p1_ips[0]]]},
                                    'network_type': 'vxlan',
@@ -253,7 +299,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 {'fdb_entries':
                                  {p1['network_id']:
                                   {'ports':
-                                   {'20.0.0.5': [constants.FLOODING_ENTRY,
+                                   {'20.0.0.5': [FLOODING_ENTRY_AS_LIST,
                                                  [p1['mac_address'],
                                                   p1_ips[0]]]},
                                    'network_type': 'vlan',
@@ -299,7 +345,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                  {'fdb_entries':
                                   {p1['network_id']:
                                    {'ports':
-                                    {'20.0.0.2': [constants.FLOODING_ENTRY,
+                                    {'20.0.0.2': [FLOODING_ENTRY_AS_LIST,
                                                   [p2['mac_address'],
                                                    p2_ips[0]]]},
                                     'network_type': 'vxlan',
@@ -320,7 +366,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                  {'fdb_entries':
                                   {p1['network_id']:
                                    {'ports':
-                                    {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                    {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                                   [p1['mac_address'],
                                                    p1_ips[0]]]},
                                     'network_type': 'vxlan',
@@ -368,7 +414,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                           {p1['network_id']:
                                            {'ports':
                                             {'20.0.0.2':
-                                             [constants.FLOODING_ENTRY,
+                                             [FLOODING_ENTRY_AS_LIST,
                                               [p1['mac_address'],
                                                p1_ips[0]]]},
                                             'network_type': 'vxlan',
@@ -392,7 +438,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                           {p1['network_id']:
                                            {'ports':
                                             {'20.0.0.1':
-                                             [constants.FLOODING_ENTRY,
+                                             [FLOODING_ENTRY_AS_LIST,
                                               [p3['mac_address'],
                                                p3_ips[0]]]},
                                             'network_type': 'vxlan',
@@ -481,7 +527,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 {'fdb_entries':
                                  {p2['network_id']:
                                   {'ports':
-                                   {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                   {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                                  [p2['mac_address'],
                                                   p2_ips[0]]]},
                                    'network_type': 'vxlan',
@@ -562,7 +608,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                             {'fdb_entries':
                              {p1['network_id']:
                               {'ports':
-                               {'20.0.0.1': [constants.FLOODING_ENTRY,
+                               {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                              [p1['mac_address'],
                                               p1_ips[0]]]},
                                'network_type': 'vxlan',
@@ -604,8 +650,8 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                  {'chg_ip':
                                   {p1['network_id']:
                                    {'20.0.0.1':
-                                    {'after': [[p1['mac_address'],
-                                                '10.0.0.10']]}}}}},
+                                    {'after': [(p1['mac_address'],
+                                                '10.0.0.10')]}}}}},
                                 'namespace': None,
                                 'method': 'update_fdb_entries'}
 
@@ -626,10 +672,10 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                  {'chg_ip':
                                   {p1['network_id']:
                                    {'20.0.0.1':
-                                    {'before': [[p1['mac_address'],
-                                                 '10.0.0.10']],
-                                     'after': [[p1['mac_address'],
-                                                '10.0.0.16']]}}}}},
+                                    {'before': [(p1['mac_address'],
+                                                 '10.0.0.10')],
+                                     'after': [(p1['mac_address'],
+                                                '10.0.0.16')]}}}}},
                                 'namespace': None,
                                 'method': 'update_fdb_entries'}
 
@@ -649,8 +695,8 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                  {'chg_ip':
                                   {p1['network_id']:
                                    {'20.0.0.1':
-                                    {'before': [[p1['mac_address'],
-                                                 '10.0.0.2']]}}}}},
+                                    {'before': [(p1['mac_address'],
+                                                 '10.0.0.2')]}}}}},
                                 'namespace': None,
                                 'method': 'update_fdb_entries'}
 
@@ -728,7 +774,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 {'fdb_entries':
                                  {p1['network_id']:
                                   {'ports':
-                                   {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                   {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                                  [p1['mac_address'],
                                                   p1_ips[0]]]},
                                    'network_type': 'vxlan',
@@ -786,7 +832,7 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                 {'fdb_entries':
                                  {p1['network_id']:
                                   {'ports':
-                                   {'20.0.0.1': [constants.FLOODING_ENTRY,
+                                   {'20.0.0.1': [FLOODING_ENTRY_AS_LIST,
                                                  [p1['mac_address'],
                                                   p1_ips[0]]]},
                                    'network_type': 'vxlan',
@@ -809,4 +855,4 @@ class TestL2PopulationRpcTestCase(test_plugin.NeutronDbPluginV2TestCase):
                                   'remove_fdb_entries')) as (upd_port_down,
                                                              rem_fdb_entries):
             l2pop_mech.delete_port_postcommit(mock.Mock())
-            self.assertTrue(upd_port_down.called)
\ No newline at end of file
+            self.assertTrue(upd_port_down.called)
index 638b40120ed8e798c2c45f6778b49ebfed6845a9..d1a79aa2f109eb188cbecd9ee0de9cd620d2d120 100644 (file)
@@ -33,10 +33,12 @@ from neutron.agent.linux import utils
 from neutron.common import constants as n_const
 from neutron.openstack.common import importutils
 from neutron.plugins.common import constants as p_const
+from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
 from neutron.tests.unit.ofagent import ofa_test_base
 
 
 NOTIFIER = ('neutron.plugins.ml2.rpc.AgentNotifierApi')
+FLOODING_ENTRY = l2pop_rpc.PortInfo(*n_const.FLOODING_ENTRY)
 
 
 def _mock_port(is_neutron=True, normalized_name=None):
@@ -560,8 +562,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
                       'segment_id': 'tun2',
                       'ports':
                       {'agent_ip':
-                       [['mac', 'ip'],
-                        n_const.FLOODING_ENTRY]}}}
+                       [l2pop_rpc.PortInfo('mac', 'ip'),
+                        FLOODING_ENTRY]}}}
         with contextlib.nested(
             mock.patch.object(self.agent.ryuapp, "add_arp_table_entry"),
             mock.patch.object(self.agent.ryuapp, "del_arp_table_entry"),
@@ -580,8 +582,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
                       'segment_id': 'tun1',
                       'ports':
                       {self.lvms[1].ip:
-                       [['mac', 'ip'],
-                        n_const.FLOODING_ENTRY]}}}
+                       [l2pop_rpc.PortInfo('mac', 'ip'),
+                        FLOODING_ENTRY]}}}
         with contextlib.nested(
             mock.patch.object(self.agent, '_setup_tunnel_port'),
             mock.patch.object(self.agent.int_br, 'install_tunnel_output'),
@@ -604,8 +606,8 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
                       'segment_id': 'tun2',
                       'ports':
                       {self.lvms[1].ip:
-                       [['mac', 'ip'],
-                        n_const.FLOODING_ENTRY]}}}
+                       [l2pop_rpc.PortInfo('mac', 'ip'),
+                        FLOODING_ENTRY]}}}
         with contextlib.nested(
             mock.patch.object(self.agent.int_br, 'install_tunnel_output'),
             mock.patch.object(self.agent.int_br, 'delete_tunnel_output'),
@@ -623,11 +625,13 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[0].net:
                      {'network_type': self.tunnel_type,
                       'segment_id': 'tun1',
-                      'ports': {self.lvms[0].ip: [['mac', 'ip']]}}}
+                      'ports': {self.lvms[0].ip: [l2pop_rpc.PortInfo('mac',
+                                                                     'ip')]}}}
         with mock.patch.object(self.agent, '_setup_tunnel_port') as add_tun_fn:
             self.agent.fdb_add(None, fdb_entry)
             self.assertFalse(add_tun_fn.called)
-            fdb_entry[self.lvms[0].net]['ports'][tunnel_ip] = [['mac', 'ip']]
+            fdb_entry[self.lvms[0].net]['ports'][tunnel_ip] = [
+                l2pop_rpc.PortInfo('mac', 'ip')]
             self.agent.fdb_add(None, fdb_entry)
             add_tun_fn.assert_called_with(
                 self.agent.int_br, tun_name, tunnel_ip, self.tunnel_type)
@@ -637,7 +641,7 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[1].net:
                      {'network_type': self.tunnel_type,
                       'segment_id': 'tun2',
-                      'ports': {self.lvms[1].ip: [n_const.FLOODING_ENTRY]}}}
+                      'ports': {self.lvms[1].ip: [FLOODING_ENTRY]}}}
         with mock.patch.object(self.agent.int_br,
                                'delete_port') as del_port_fn:
             self.agent.fdb_remove(None, fdb_entry)
@@ -648,11 +652,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[0].net:
                      {'network_type': self.tunnel_type,
                       'segment_id': 'tun1',
-                      'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY,
-                                                  ['mac1', 'ip1']],
-                                self.lvms[1].ip: [['mac2', 'ip2']],
-                                '192.0.2.1': [n_const.FLOODING_ENTRY,
-                                              ['mac3', 'ip3']]}}}
+                      'ports': {self.lvms[0].ip: [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac1', 'ip1')],
+                                self.lvms[1].ip: [
+                                    l2pop_rpc.PortInfo('mac2', 'ip2')],
+                                '192.0.2.1': [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
         with mock.patch.object(self.agent,
                                'setup_tunnel_port') as setup_tun_fn:
             self.agent.fdb_add(None, fdb_entry)
@@ -671,11 +678,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[0].net:
                      {'network_type': network_type,
                       'segment_id': 'tun1',
-                      'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY,
-                                                  ['mac1', 'ip1']],
-                                self.lvms[1].ip: [['mac2', 'ip2']],
-                                '192.0.2.1': [n_const.FLOODING_ENTRY,
-                                              ['mac3', 'ip3']]}}}
+                      'ports': {self.lvms[0].ip: [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac1', 'ip1')],
+                                self.lvms[1].ip: [
+                                    l2pop_rpc.PortInfo('mac2', 'ip2')],
+                                '192.0.2.1': [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
         with mock.patch.object(self.agent,
                                'setup_tunnel_port') as setup_tun_fn:
             self.agent.fdb_add(None, fdb_entry)
@@ -702,11 +712,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[0].net:
                      {'network_type': self.tunnel_type,
                       'segment_id': 'tun1',
-                      'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY,
-                                                  ['mac1', 'ip1']],
-                                self.lvms[1].ip: [['mac2', 'ip2']],
-                                '192.0.2.1': [n_const.FLOODING_ENTRY,
-                                              ['mac3', 'ip3']]}}}
+                      'ports': {self.lvms[0].ip: [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac1', 'ip1')],
+                                self.lvms[1].ip: [
+                                    l2pop_rpc.PortInfo('mac2', 'ip2')],
+                                '192.0.2.1': [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
         with mock.patch.object(self.agent,
                                'cleanup_tunnel_port') as cleanup_tun_fn:
             self.agent.fdb_remove(None, fdb_entry)
@@ -724,11 +737,14 @@ class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
         fdb_entry = {self.lvms[0].net:
                      {'network_type': network_type,
                       'segment_id': 'tun1',
-                      'ports': {self.lvms[0].ip: [n_const.FLOODING_ENTRY,
-                                                  ['mac1', 'ip1']],
-                                self.lvms[1].ip: [['mac2', 'ip2']],
-                                '192.0.2.1': [n_const.FLOODING_ENTRY,
-                                              ['mac3', 'ip3']]}}}
+                      'ports': {self.lvms[0].ip: [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac1', 'ip1')],
+                                self.lvms[1].ip: [
+                                    l2pop_rpc.PortInfo('mac2', 'ip2')],
+                                '192.0.2.1': [
+                                    FLOODING_ENTRY,
+                                    l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
         with mock.patch.object(self.agent,
                                'cleanup_tunnel_port') as cleanup_tun_fn:
             self.agent.fdb_remove(None, fdb_entry)
index 73d62b3dff2657c18228ea0d068fb53bc322dd72..376b1c03c0aed11016b1de0d777f00db3b48513b 100644 (file)
@@ -27,6 +27,7 @@ from neutron.agent.linux import utils
 from neutron.common import constants as n_const
 from neutron.openstack.common import log
 from neutron.plugins.common import constants as p_const
+from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
 from neutron.plugins.openvswitch.agent import ovs_neutron_agent
 from neutron.plugins.openvswitch.common import constants
 from neutron.tests import base
@@ -1030,7 +1031,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
                       'segment_id': 'tun2',
                       'ports':
                       {'agent_ip':
-                       [[FAKE_MAC, FAKE_IP1],
+                       [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1),
                         n_const.FLOODING_ENTRY]}}}
         with mock.patch.object(self.agent.tun_br,
                                "deferred") as defer_fn:
@@ -1047,7 +1048,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
                       'segment_id': 'tun1',
                       'ports':
                       {'2.2.2.2':
-                       [[FAKE_MAC, FAKE_IP1],
+                       [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1),
                         n_const.FLOODING_ENTRY]}}}
 
         class ActionMatcher(object):
@@ -1102,7 +1103,7 @@ class TestOvsNeutronAgent(base.BaseTestCase):
                       'segment_id': 'tun2',
                       'ports':
                       {'2.2.2.2':
-                       [[FAKE_MAC, FAKE_IP1],
+                       [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1),
                         n_const.FLOODING_ENTRY]}}}
         with contextlib.nested(
             mock.patch.object(self.agent.tun_br, 'deferred'),
@@ -1132,7 +1133,8 @@ class TestOvsNeutronAgent(base.BaseTestCase):
         fdb_entry = {'net1':
                      {'network_type': 'gre',
                       'segment_id': 'tun1',
-                      'ports': {'1.1.1.1': [[FAKE_MAC, FAKE_IP1]]}}}
+                      'ports': {'1.1.1.1': [l2pop_rpc.PortInfo(FAKE_MAC,
+                                                               FAKE_IP1)]}}}
         with contextlib.nested(
             mock.patch.object(self.agent.tun_br, 'deferred'),
             mock.patch.object(self.agent.tun_br, 'do_action_flows'),
@@ -1142,7 +1144,8 @@ class TestOvsNeutronAgent(base.BaseTestCase):
             deferred_fn.return_value = deferred_br
             self.agent.fdb_add(None, fdb_entry)
             self.assertFalse(add_tun_fn.called)
-            fdb_entry['net1']['ports']['10.10.10.10'] = [[FAKE_MAC, FAKE_IP1]]
+            fdb_entry['net1']['ports']['10.10.10.10'] = [
+                l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1)]
             self.agent.fdb_add(None, fdb_entry)
             add_tun_fn.assert_called_with(
                 deferred_br, 'gre-0a0a0a0a', '10.10.10.10', 'gre')
@@ -1168,8 +1171,8 @@ class TestOvsNeutronAgent(base.BaseTestCase):
         fdb_entries = {'chg_ip':
                        {'net1':
                         {'agent_ip':
-                         {'before': [[FAKE_MAC, FAKE_IP1]],
-                          'after': [[FAKE_MAC, FAKE_IP2]]}}}}
+                         {'before': [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP1)],
+                          'after': [l2pop_rpc.PortInfo(FAKE_MAC, FAKE_IP2)]}}}}
         with contextlib.nested(
             mock.patch.object(self.agent.tun_br, 'deferred'),
             mock.patch.object(self.agent.tun_br, 'do_action_flows'),