'Calculate changes in IPs for the port.'

def _get_changed_ips_for_port(self, context, original_ips, new_ips, device_owner):

    delete_subnet_ids = set((ip['subnet_id'] for ip in new_ips if ip.get('delete_subnet')))
    ips = [ip for ip in new_ips if (ip.get('subnet_id') not in delete_subnet_ids)]
    (add_ips, prev_ips, remove_candidates) = ([], [], [])
    orig_by_ip = {ip['ip_address']: ip for ip in original_ips}
    for ip in ips:
        if ('ip_address' not in ip):
            continue
        original = orig_by_ip.pop(ip['ip_address'], None)
        if original:
            prev_ips.append(original)
        else:
            add_ips.append(ip)
    orig_by_subnet = collections.defaultdict(list)
    for ip in orig_by_ip.values():
        orig_by_subnet[ip['subnet_id']].append(ip)
    for ip in ips:
        if ('ip_address' in ip):
            continue
        orig = orig_by_subnet.get(ip['subnet_id'])
        if (not orig):
            add_ips.append(ip)
            continue
        orig_ip = orig.pop()
        if ipv6_utils.is_eui64_address(orig_ip['ip_address']):
            add_ips.append(ip)
            remove_candidates.append(orig_ip)
        else:
            prev_ips.append(orig_ip)
    maybe_remove = itertools.chain(itertools.chain.from_iterable(orig_by_subnet.values()), remove_candidates)
    remove_ips = []
    for ip in maybe_remove:
        subnet_id = ip['subnet_id']
        ip_required = self._is_ip_required_by_subnet(context, subnet_id, device_owner)
        if (ip_required or (subnet_id in delete_subnet_ids)):
            remove_ips.append(ip)
        else:
            prev_ips.append(ip)
    return self.Changes(add=add_ips, original=prev_ips, remove=remove_ips)
