diff -crB --new-file neutron-9.4.2.dev21-backup/neutron/agent/common/ovs_lib.py neutron-9.4.2.dev21/neutron/agent/common/ovs_lib.py
*** neutron-9.4.2.dev21-backup/neutron/agent/common/ovs_lib.py	2019-08-15 11:41:11.189960600 -0700
--- neutron-9.4.2.dev21/neutron/agent/common/ovs_lib.py	2019-08-15 11:44:23.475389850 -0700
***************
*** 30,35 ****
--- 30,36 ----
  from neutron.agent.common import utils
  from neutron.agent.linux import ip_lib
  from neutron.agent.ovsdb import api as ovsdb
+ from neutron.common import constants as common_constants
  from neutron.conf.agent import ovs_conf
  from neutron.plugins.common import constants as p_const
  from neutron.plugins.ml2.drivers.openvswitch.agent.common \
***************
*** 332,338 ****
                  if 'cookie' not in kw:
                      kw['cookie'] = self._default_cookie
          flow_strs = [_build_flow_expr_str(kw, action) for kw in kwargs_list]
!         self.run_ofctl('%s-flows' % action, ['-'], '\n'.join(flow_strs))
  
      def add_flow(self, **kwargs):
          self.do_action_flows('add', [kwargs])
--- 333,343 ----
                  if 'cookie' not in kw:
                      kw['cookie'] = self._default_cookie
          flow_strs = [_build_flow_expr_str(kw, action) for kw in kwargs_list]
!         LOG.debug("Processing %d OpenFlow rules.", len(flow_strs))
!         step = common_constants.AGENT_RES_PROCESSING_STEP
!         for i in range(0, len(flow_strs), step):
!             self.run_ofctl('%s-flows' % action, ['-'],
!                            '\n'.join(flow_strs[i:i + step]))
  
      def add_flow(self, **kwargs):
          self.do_action_flows('add', [kwargs])
diff -crB --new-file neutron-9.4.2.dev21-backup/neutron/agent/securitygroups_rpc.py neutron-9.4.2.dev21/neutron/agent/securitygroups_rpc.py
*** neutron-9.4.2.dev21-backup/neutron/agent/securitygroups_rpc.py	2017-09-23 11:10:44.000000000 -0700
--- neutron-9.4.2.dev21/neutron/agent/securitygroups_rpc.py	2019-08-15 11:44:23.475389850 -0700
***************
*** 23,28 ****
--- 23,29 ----
  from neutron._i18n import _LI, _LW
  from neutron.agent import firewall
  from neutron.api.rpc.handlers import securitygroups_rpc
+ from neutron.common import constants as common_constants
  from neutron.conf.agent import securitygroups_rpc as sc_cfg
  
  
***************
*** 138,149 ****
          self._apply_port_filter(device_ids)
  
      def _apply_port_filter(self, device_ids, update_filter=False):
          if self.use_enhanced_rpc:
!             devices_info = self.plugin_rpc.security_group_info_for_devices(
!                 self.context, list(device_ids))
!             devices = devices_info['devices']
!             security_groups = devices_info['security_groups']
!             security_group_member_ips = devices_info['sg_member_ips']
          else:
              devices = self.plugin_rpc.security_group_rules_for_devices(
                  self.context, list(device_ids))
--- 139,155 ----
          self._apply_port_filter(device_ids)
  
      def _apply_port_filter(self, device_ids, update_filter=False):
+         step = common_constants.AGENT_RES_PROCESSING_STEP
          if self.use_enhanced_rpc:
!             devices = {}
!             security_groups = {}
!             security_group_member_ips = {}
!             for i in range(0, len(device_ids), step):
!                 devices_info = self.plugin_rpc.security_group_info_for_devices(
!                     self.context, list(device_ids)[i:i + step])
!                 devices.update(devices_info['devices'])
!                 security_groups.update(devices_info['security_groups'])
!                 security_group_member_ips.update(devices_info['sg_member_ips'])
          else:
              devices = self.plugin_rpc.security_group_rules_for_devices(
                  self.context, list(device_ids))
diff -crB --new-file neutron-9.4.2.dev21-backup/neutron/common/constants.py neutron-9.4.2.dev21/neutron/common/constants.py
*** neutron-9.4.2.dev21-backup/neutron/common/constants.py	2019-08-15 11:32:05.669913176 -0700
--- neutron-9.4.2.dev21/neutron/common/constants.py	2019-08-15 11:44:23.475389850 -0700
***************
*** 155,160 ****
--- 155,172 ----
  # Do not move this constant to neutron-lib, since it is temporary
  IPTABLES_RANDOM_FULLY_VERSION = '1.6.2'
  
+ # Number of resources for neutron agent side functions to deal
+ # with large sets.
+ # Setting this value does not count on special conditions, it is just a human
+ # countable or scalable number. [1] gives us the method to test the scale
+ # issue. And we have tested the value of 1000, 500, 200, 100. But for 100,
+ # ovs-agent will have a lower timeout probability. And according to the
+ # testing result, step size 100 can indeed cost about 10% much more time
+ # than 500/1000. But such extra time looks inevitably needed to be sacrificed
+ # for the restart success rate.
+ # [1] http://paste.openstack.org/show/745685/
+ AGENT_RES_PROCESSING_STEP = 100
+ 
  # Neutron-lib migration shim. This will emit a deprecation warning on any
  # reference to constants that have been moved out of this module and into
  # the neutron_lib.constants module.
diff -crB --new-file neutron-9.4.2.dev21-backup/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py neutron-9.4.2.dev21/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py
*** neutron-9.4.2.dev21-backup/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py	2019-08-15 11:41:11.189960600 -0700
--- neutron-9.4.2.dev21/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py	2019-08-15 11:44:23.479389880 -0700
***************
*** 1664,1669 ****
--- 1664,1670 ----
                                   port_info.get('updated', set()))
          need_binding_devices = []
          skipped_devices = set()
+         start = time.time()
          if devices_added_updated:
              start = time.time()
              (skipped_devices, need_binding_devices,
***************
*** 1690,1695 ****
--- 1691,1700 ----
          self._add_port_tag_info(need_binding_devices)
          self.sg_agent.setup_port_filters(added_ports,
                                           port_info.get('updated', set()))
+         LOG.info(_LI("process_network_ports - iteration:%(iter_num)d - "
+                      "agent port security group processed in %(elapsed).3f"),
+                  {'iter_num': self.iter_num,
+                   'elapsed': time.time() - start})
          failed_devices['added'] |= self._bind_devices(need_binding_devices)
  
          if 'removed' in port_info and port_info['removed']:
diff -crB --new-file neutron-9.4.2.dev21-backup/neutron/tests/unit/agent/test_securitygroups_rpc.py neutron-9.4.2.dev21/neutron/tests/unit/agent/test_securitygroups_rpc.py
*** neutron-9.4.2.dev21-backup/neutron/tests/unit/agent/test_securitygroups_rpc.py	2017-09-23 11:10:44.000000000 -0700
--- neutron-9.4.2.dev21/neutron/tests/unit/agent/test_securitygroups_rpc.py	2019-08-15 11:44:23.479389880 -0700
***************
*** 1304,1310 ****
                                          mock.call.defer_apply(),
                                          mock.call.remove_port_filter(
                                              self.fake_device),
!                                         ])
  
      def test_security_groups_rule_updated_enhanced_rpc(self):
          sg_list = ['fake_sgid1', 'fake_sgid3']
--- 1304,1310 ----
                                          mock.call.defer_apply(),
                                          mock.call.remove_port_filter(
                                              self.fake_device),
!                                         ], any_order=True)
  
      def test_security_groups_rule_updated_enhanced_rpc(self):
          sg_list = ['fake_sgid1', 'fake_sgid3']
***************
*** 1365,1371 ****
                       'fake_sgid2', {'IPv4': [], 'IPv6': []}),
                   mock.call.update_port_filter(self.fake_device)]
  
!         self.firewall.assert_has_calls(calls)
  
      def test_refresh_firewall_devices_enhanced_rpc(self):
          self.agent.prepare_devices_filter(['fake_device'])
--- 1365,1371 ----
                       'fake_sgid2', {'IPv4': [], 'IPv6': []}),
                   mock.call.update_port_filter(self.fake_device)]
  
!         self.firewall.assert_has_calls(calls, any_order=True)
  
      def test_refresh_firewall_devices_enhanced_rpc(self):
          self.agent.prepare_devices_filter(['fake_device'])
***************
*** 1386,1392 ****
                       'IPv4': [], 'IPv6': []}),
                   mock.call.update_port_filter(self.fake_device)
                   ]
!         self.firewall.assert_has_calls(calls)
  
      def test_refresh_firewall_none_enhanced_rpc(self):
          self.agent.refresh_firewall([])
--- 1386,1392 ----
                       'IPv4': [], 'IPv6': []}),
                   mock.call.update_port_filter(self.fake_device)
                   ]
!         self.firewall.assert_has_calls(calls, any_order=True)
  
      def test_refresh_firewall_none_enhanced_rpc(self):
          self.agent.refresh_firewall([])
