diff --git a/lower-constraints.txt b/lower-constraints.txt
index 09aabede1f..861749b738 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -38,7 +38,7 @@ msgpack-python==0.4.0
 munch==2.1.0
 netaddr==0.7.18
 netifaces==0.10.4
-openstacksdk==0.53.0
+openstacksdk==0.56.0
 os-client-config==2.1.0
 os-service-types==1.7.0
 osc-lib==2.3.0
diff --git a/openstackclient/network/common.py b/openstackclient/network/common.py
index 47ffbe77a6..b1902a6c9c 100644
--- a/openstackclient/network/common.py
+++ b/openstackclient/network/common.py
@@ -16,10 +16,12 @@ import contextlib
 import logging
 
 import openstack.exceptions
+from osc_lib.cli import parseractions
 from osc_lib.command import command
 from osc_lib import exceptions
 
 from openstackclient.i18n import _
+from openstackclient.network import utils
 
 
 LOG = logging.getLogger(__name__)
@@ -75,7 +77,6 @@ class NetDetectionMixin(metaclass=abc.ABCMeta):
         """
         # Have we set it up yet for this command?
         if not hasattr(self, '_net_type'):
-            # import pdb; pdb.set_trace()
             try:
                 if self.app.client_manager.is_network_endpoint_enabled():
                     net_type = _NET_TYPE_NEUTRON
@@ -255,3 +256,74 @@ class NetworkAndComputeShowOne(NetDetectionMixin, command.ShowOne,
             if exc.details:
                 msg += ", " + str(exc.details)
             raise exceptions.CommandError(msg)
+
+
+class NeutronCommandWithExtraArgs(command.Command):
+    """Create and Update commands with additional extra properties.
+
+    Extra properties can be passed to the command and are then send to the
+    Neutron as given to the command.
+    """
+
+    # dict of allowed types
+    _allowed_types_dict = {
+        'bool': utils.str2bool,
+        'dict': utils.str2dict,
+        'list': utils.str2list,
+        'int': int,
+        'str': str,
+    }
+
+    def _get_property_converter(self, _property):
+        if 'type' not in _property:
+            converter = str
+        else:
+            converter = self._allowed_types_dict.get(_property['type'])
+
+        if not converter:
+            raise exceptions.CommandError(
+                _("Type {property_type} of property {name} "
+                  "is not supported").format(
+                      property_type=_property['type'],
+                      name=_property['name']))
+        return converter
+
+    def _parse_extra_properties(self, extra_properties):
+        result = {}
+        if extra_properties:
+            for _property in extra_properties:
+                converter = self._get_property_converter(_property)
+                result[_property['name']] = converter(_property['value'])
+        return result
+
+    def get_parser(self, prog_name):
+        parser = super(NeutronCommandWithExtraArgs, self).get_parser(prog_name)
+        parser.add_argument(
+            '--extra-property',
+            metavar='type=<property_type>,name=<property_name>,'
+                    'value=<property_value>',
+            dest='extra_properties',
+            action=parseractions.MultiKeyValueAction,
+            required_keys=['name', 'value'],
+            optional_keys=['type'],
+            help=_("Additional parameters can be passed using this property. "
+                   "Default type of the extra property is string ('str'), but "
+                   "other types can be used as well. Available types are: "
+                   "'dict', 'list', 'str', 'bool', 'int'. "
+                   "In case of 'list' type, 'value' can be "
+                   "semicolon-separated list of values. "
+                   "For 'dict' value is semicolon-separated list of the "
+                   "key:value pairs.")
+        )
+        return parser
+
+
+class NeutronUnsetCommandWithExtraArgs(NeutronCommandWithExtraArgs):
+
+    def _parse_extra_properties(self, extra_properties):
+        result = {}
+        if extra_properties:
+            for _property in extra_properties:
+                result[_property['name']] = None
+
+        return result
diff --git a/openstackclient/network/utils.py b/openstackclient/network/utils.py
index 287f027163..4d4d18e470 100644
--- a/openstackclient/network/utils.py
+++ b/openstackclient/network/utils.py
@@ -11,6 +11,10 @@
 #   under the License.
 #
 
+from osc_lib import exceptions
+
+from openstackclient.i18n import _
+
 
 # Transform compute security group rule for display.
 def transform_compute_security_group_rule(sg_rule):
@@ -39,3 +43,41 @@ def transform_compute_security_group_rule(sg_rule):
     else:
         info['remote_security_group'] = ''
     return info
+
+
+def str2bool(strbool):
+    if strbool is None:
+        return None
+    return strbool.lower() == 'true'
+
+
+def str2list(strlist):
+    result = []
+    if strlist:
+        result = strlist.split(';')
+    return result
+
+
+def str2dict(strdict):
+    """Convert key1:value1;key2:value2;... string into dictionary.
+
+    :param strdict: string in the form of key1:value1;key2:value2
+    """
+    result = {}
+    if not strdict:
+        return result
+    i = 0
+    kvlist = []
+    for kv in strdict.split(';'):
+        if ':' in kv:
+            kvlist.append(kv)
+            i += 1
+        elif i == 0:
+            msg = _("missing value for key '%s'")
+            raise exceptions.CommandError(msg % kv)
+        else:
+            kvlist[i - 1] = "%s;%s" % (kvlist[i - 1], kv)
+    for kv in kvlist:
+        key, sep, value = kv.partition(':')
+        result[key] = value
+    return result
diff --git a/openstackclient/network/v2/address_group.py b/openstackclient/network/v2/address_group.py
index c5b2f12606..fc83470053 100644
--- a/openstackclient/network/v2/address_group.py
+++ b/openstackclient/network/v2/address_group.py
@@ -22,6 +22,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -57,7 +58,7 @@ def _get_attrs(client_manager, parsed_args):
     return attrs
 
 
-class CreateAddressGroup(command.ShowOne):
+class CreateAddressGroup(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a new Address Group")
 
     def get_parser(self, prog_name):
@@ -93,6 +94,9 @@ class CreateAddressGroup(command.ShowOne):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         obj = client.create_address_group(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
@@ -191,7 +195,7 @@ class ListAddressGroup(command.Lister):
                 ) for s in data))
 
 
-class SetAddressGroup(command.Command):
+class SetAddressGroup(common.NeutronCommandWithExtraArgs):
     _description = _("Set address group properties")
 
     def get_parser(self, prog_name):
@@ -231,6 +235,9 @@ class SetAddressGroup(command.Command):
             attrs['name'] = parsed_args.name
         if parsed_args.description is not None:
             attrs['description'] = parsed_args.description
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_address_group(obj, **attrs)
         if parsed_args.address:
diff --git a/openstackclient/network/v2/address_scope.py b/openstackclient/network/v2/address_scope.py
index 71c1a9afb7..cd27678ee9 100644
--- a/openstackclient/network/v2/address_scope.py
+++ b/openstackclient/network/v2/address_scope.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -57,7 +58,7 @@ def _get_attrs(client_manager, parsed_args):
 
 # TODO(rtheis): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateAddressScope(command.ShowOne):
+class CreateAddressScope(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a new Address Scope")
 
     def get_parser(self, prog_name):
@@ -98,6 +99,8 @@ class CreateAddressScope(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_address_scope(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
@@ -226,7 +229,7 @@ class ListAddressScope(command.Lister):
 
 # TODO(rtheis): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetAddressScope(command.Command):
+class SetAddressScope(common.NeutronCommandWithExtraArgs):
     _description = _("Set address scope properties")
 
     def get_parser(self, prog_name):
@@ -267,6 +270,8 @@ class SetAddressScope(command.Command):
             attrs['shared'] = True
         if parsed_args.no_share:
             attrs['shared'] = False
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         client.update_address_scope(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/floating_ip.py b/openstackclient/network/v2/floating_ip.py
index a2765cd1ef..25b2a1baf6 100644
--- a/openstackclient/network/v2/floating_ip.py
+++ b/openstackclient/network/v2/floating_ip.py
@@ -13,7 +13,6 @@
 
 """IP Floating action implementations"""
 
-from osc_lib.command import command
 from osc_lib import utils
 from osc_lib.utils import tags as _tag
 
@@ -94,7 +93,8 @@ def _get_attrs(client_manager, parsed_args):
     return attrs
 
 
-class CreateFloatingIP(common.NetworkAndComputeShowOne):
+class CreateFloatingIP(common.NetworkAndComputeShowOne,
+                       common.NeutronCommandWithExtraArgs):
     _description = _("Create floating IP")
 
     def update_parser_common(self, parser):
@@ -175,6 +175,8 @@ class CreateFloatingIP(common.NetworkAndComputeShowOne):
 
     def take_action_network(self, client, parsed_args):
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         with common.check_missing_extension_if_error(
                 self.app.client_manager.network, attrs):
             obj = client.create_ip(**attrs)
@@ -390,7 +392,7 @@ class ListFloatingIP(common.NetworkAndComputeLister):
                 ) for s in data))
 
 
-class SetFloatingIP(command.Command):
+class SetFloatingIP(common.NeutronCommandWithExtraArgs):
     _description = _("Set floating IP Properties")
 
     def get_parser(self, prog_name):
@@ -456,6 +458,9 @@ class SetFloatingIP(command.Command):
         if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
             attrs['qos_policy_id'] = None
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_ip(obj, **attrs)
 
@@ -490,7 +495,7 @@ class ShowFloatingIP(common.NetworkAndComputeShowOne):
         return (columns, data)
 
 
-class UnsetFloatingIP(command.Command):
+class UnsetFloatingIP(common.NeutronCommandWithExtraArgs):
     _description = _("Unset floating IP Properties")
 
     def get_parser(self, prog_name):
@@ -526,6 +531,8 @@ class UnsetFloatingIP(command.Command):
             attrs['port_id'] = None
         if parsed_args.qos_policy:
             attrs['qos_policy_id'] = None
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
 
         if attrs:
             client.update_ip(obj, **attrs)
diff --git a/openstackclient/network/v2/floating_ip_port_forwarding.py b/openstackclient/network/v2/floating_ip_port_forwarding.py
index 06b3df8bcd..71b0b7da63 100644
--- a/openstackclient/network/v2/floating_ip_port_forwarding.py
+++ b/openstackclient/network/v2/floating_ip_port_forwarding.py
@@ -19,6 +19,7 @@ from osc_lib import exceptions
 from osc_lib import utils
 
 from openstackclient.i18n import _
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -32,7 +33,8 @@ def _get_columns(item):
     return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
 
 
-class CreateFloatingIPPortForwarding(command.ShowOne):
+class CreateFloatingIPPortForwarding(command.ShowOne,
+                                     common.NeutronCommandWithExtraArgs):
     _description = _("Create floating IP port forwarding")
 
     def get_parser(self, prog_name):
@@ -122,6 +124,9 @@ class CreateFloatingIPPortForwarding(command.ShowOne):
         if parsed_args.description is not None:
             attrs['description'] = parsed_args.description
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         obj = client.create_floating_ip_port_forwarding(
             floating_ip.id,
             **attrs
@@ -258,7 +263,7 @@ class ListFloatingIPPortForwarding(command.Lister):
                 ) for s in data))
 
 
-class SetFloatingIPPortForwarding(command.Command):
+class SetFloatingIPPortForwarding(common.NeutronCommandWithExtraArgs):
     _description = _("Set floating IP Port Forwarding Properties")
 
     def get_parser(self, prog_name):
@@ -352,6 +357,9 @@ class SetFloatingIPPortForwarding(command.Command):
         if parsed_args.description is not None:
             attrs['description'] = parsed_args.description
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         client.update_floating_ip_port_forwarding(
             floating_ip.id, parsed_args.port_forwarding_id, **attrs)
 
diff --git a/openstackclient/network/v2/network.py b/openstackclient/network/v2/network.py
index 7a12d523e2..b8eb9f014b 100644
--- a/openstackclient/network/v2/network.py
+++ b/openstackclient/network/v2/network.py
@@ -15,7 +15,6 @@
 
 from cliff import columns as cliff_columns
 from osc_lib.cli import format_columns
-from osc_lib.command import command
 from osc_lib import utils
 from osc_lib.utils import tags as _tag
 
@@ -189,7 +188,8 @@ def _add_additional_network_options(parser):
 
 # TODO(sindhu): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateNetwork(common.NetworkAndComputeShowOne):
+class CreateNetwork(common.NetworkAndComputeShowOne,
+                    common.NeutronCommandWithExtraArgs):
     _description = _("Create new network")
 
     def update_parser_common(self, parser):
@@ -334,6 +334,8 @@ class CreateNetwork(common.NetworkAndComputeShowOne):
             attrs['vlan_transparent'] = True
         if parsed_args.no_transparent_vlan:
             attrs['vlan_transparent'] = False
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         with common.check_missing_extension_if_error(
                 self.app.client_manager.network, attrs):
             obj = client.create_network(**attrs)
@@ -623,7 +625,7 @@ class ListNetwork(common.NetworkAndComputeLister):
 
 # TODO(sindhu): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetNetwork(command.Command):
+class SetNetwork(common.NeutronCommandWithExtraArgs):
     _description = _("Set network properties")
 
     def get_parser(self, prog_name):
@@ -728,6 +730,8 @@ class SetNetwork(command.Command):
         obj = client.find_network(parsed_args.network, ignore_missing=False)
 
         attrs = _get_attrs_network(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         if attrs:
             with common.check_missing_extension_if_error(
                     self.app.client_manager.network, attrs):
@@ -761,7 +765,7 @@ class ShowNetwork(common.NetworkAndComputeShowOne):
         return (display_columns, data)
 
 
-class UnsetNetwork(command.Command):
+class UnsetNetwork(common.NeutronUnsetCommandWithExtraArgs):
     _description = _("Unset network properties")
 
     def get_parser(self, prog_name):
@@ -778,8 +782,9 @@ class UnsetNetwork(command.Command):
         client = self.app.client_manager.network
         obj = client.find_network(parsed_args.network, ignore_missing=False)
 
-        # NOTE: As of now, UnsetNetwork has no attributes which need
-        # to be updated by update_network().
+        attrs = self._parse_extra_properties(parsed_args.extra_properties)
+        if attrs:
+            client.update_network(obj, **attrs)
 
         # tags is a subresource and it needs to be updated separately.
         _tag.update_tags_for_unset(client, obj, parsed_args)
diff --git a/openstackclient/network/v2/network_flavor.py b/openstackclient/network/v2/network_flavor.py
index c9d368bfc1..9e758ae29c 100644
--- a/openstackclient/network/v2/network_flavor.py
+++ b/openstackclient/network/v2/network_flavor.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -88,7 +89,7 @@ class AddNetworkFlavorToProfile(command.Command):
 
 # TODO(dasanind): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateNetworkFlavor(command.ShowOne):
+class CreateNetworkFlavor(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create new network flavor")
 
     def get_parser(self, prog_name):
@@ -134,6 +135,8 @@ class CreateNetworkFlavor(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_flavor(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
@@ -234,7 +237,7 @@ class RemoveNetworkFlavorFromProfile(command.Command):
 
 # TODO(dasanind): Use only the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetNetworkFlavor(command.Command):
+class SetNetworkFlavor(common.NeutronCommandWithExtraArgs):
     _description = _("Set network flavor properties")
 
     def get_parser(self, prog_name):
@@ -281,6 +284,8 @@ class SetNetworkFlavor(command.Command):
             attrs['enabled'] = True
         if parsed_args.disable:
             attrs['enabled'] = False
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         client.update_flavor(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/network_flavor_profile.py b/openstackclient/network/v2/network_flavor_profile.py
index 6cf0c4124d..0212e0d9ba 100644
--- a/openstackclient/network/v2/network_flavor_profile.py
+++ b/openstackclient/network/v2/network_flavor_profile.py
@@ -19,6 +19,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -60,7 +61,8 @@ def _get_attrs(client_manager, parsed_args):
 
 # TODO(ndahiwade): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateNetworkFlavorProfile(command.ShowOne):
+class CreateNetworkFlavorProfile(command.ShowOne,
+                                 common.NeutronCommandWithExtraArgs):
     _description = _("Create new network flavor profile")
 
     def get_parser(self, prog_name):
@@ -103,6 +105,8 @@ class CreateNetworkFlavorProfile(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
 
         if parsed_args.driver is None and parsed_args.metainfo is None:
             msg = _("Either --driver or --metainfo or both are required")
@@ -180,7 +184,7 @@ class ListNetworkFlavorProfile(command.Lister):
 
 # TODO(ndahiwade): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetNetworkFlavorProfile(command.Command):
+class SetNetworkFlavorProfile(common.NeutronCommandWithExtraArgs):
     _description = _("Set network flavor profile properties")
 
     def get_parser(self, prog_name):
@@ -225,6 +229,8 @@ class SetNetworkFlavorProfile(command.Command):
         obj = client.find_service_profile(parsed_args.flavor_profile,
                                           ignore_missing=False)
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
 
         client.update_service_profile(obj, **attrs)
 
diff --git a/openstackclient/network/v2/network_meter.py b/openstackclient/network/v2/network_meter.py
index df0e1da119..f8f188a806 100644
--- a/openstackclient/network/v2/network_meter.py
+++ b/openstackclient/network/v2/network_meter.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 LOG = logging.getLogger(__name__)
@@ -59,7 +60,7 @@ def _get_attrs(client_manager, parsed_args):
 
 # TODO(ankur-gupta-f): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateMeter(command.ShowOne):
+class CreateMeter(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create network meter")
 
     def get_parser(self, prog_name):
@@ -100,6 +101,8 @@ class CreateMeter(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_metering_label(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
diff --git a/openstackclient/network/v2/network_meter_rule.py b/openstackclient/network/v2/network_meter_rule.py
index 1cf0395f44..06362fa14c 100644
--- a/openstackclient/network/v2/network_meter_rule.py
+++ b/openstackclient/network/v2/network_meter_rule.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 LOG = logging.getLogger(__name__)
@@ -64,7 +65,7 @@ def _get_attrs(client_manager, parsed_args):
     return attrs
 
 
-class CreateMeterRule(command.ShowOne):
+class CreateMeterRule(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a new meter rule")
 
     def get_parser(self, prog_name):
@@ -130,6 +131,8 @@ class CreateMeterRule(command.ShowOne):
                                             ignore_missing=False)
         parsed_args.meter = _meter.id
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_metering_label_rule(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
diff --git a/openstackclient/network/v2/network_qos_policy.py b/openstackclient/network/v2/network_qos_policy.py
index fd5ff93771..7300a5c0ac 100644
--- a/openstackclient/network/v2/network_qos_policy.py
+++ b/openstackclient/network/v2/network_qos_policy.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -67,7 +68,8 @@ def _get_attrs(client_manager, parsed_args):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateNetworkQosPolicy(command.ShowOne):
+class CreateNetworkQosPolicy(command.ShowOne,
+                             common.NeutronCommandWithExtraArgs):
     _description = _("Create a QoS policy")
 
     def get_parser(self, prog_name):
@@ -117,6 +119,8 @@ class CreateNetworkQosPolicy(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_qos_policy(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters={})
@@ -209,7 +213,7 @@ class ListNetworkQosPolicy(command.Lister):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetNetworkQosPolicy(command.Command):
+class SetNetworkQosPolicy(common.NeutronCommandWithExtraArgs):
     _description = _("Set QoS policy properties")
 
     def get_parser(self, prog_name):
@@ -259,6 +263,8 @@ class SetNetworkQosPolicy(command.Command):
             parsed_args.policy,
             ignore_missing=False)
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         client.update_qos_policy(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/network_qos_rule.py b/openstackclient/network/v2/network_qos_rule.py
index 2e4b385d2e..f30a5aeb1f 100644
--- a/openstackclient/network/v2/network_qos_rule.py
+++ b/openstackclient/network/v2/network_qos_rule.py
@@ -20,6 +20,7 @@ from osc_lib import exceptions
 from osc_lib import utils
 
 from openstackclient.i18n import _
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -171,7 +172,8 @@ def _add_rule_arguments(parser):
     )
 
 
-class CreateNetworkQosRule(command.ShowOne):
+class CreateNetworkQosRule(command.ShowOne,
+                           common.NeutronCommandWithExtraArgs):
     _description = _("Create new Network QoS rule")
 
     def get_parser(self, prog_name):
@@ -198,6 +200,8 @@ class CreateNetworkQosRule(command.ShowOne):
     def take_action(self, parsed_args):
         network_client = self.app.client_manager.network
         attrs = _get_attrs(network_client, parsed_args, is_create=True)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         try:
             obj = _rule_action_call(
                 network_client, ACTION_CREATE, parsed_args.type)(
@@ -285,7 +289,7 @@ class ListNetworkQosRule(command.Lister):
                 (_get_item_properties(s, columns) for s in data))
 
 
-class SetNetworkQosRule(command.Command):
+class SetNetworkQosRule(common.NeutronCommandWithExtraArgs):
     _description = _("Set Network QoS rule properties")
 
     def get_parser(self, prog_name):
@@ -312,6 +316,8 @@ class SetNetworkQosRule(command.Command):
             if not rule_type:
                 raise Exception('Rule not found')
             attrs = _get_attrs(network_client, parsed_args)
+            attrs.update(
+                self._parse_extra_properties(parsed_args.extra_properties))
             qos_id = attrs.pop('qos_policy_id')
             qos_rule = _rule_action_call(network_client, ACTION_FIND,
                                          rule_type)(attrs.pop('id'), qos_id)
diff --git a/openstackclient/network/v2/network_rbac.py b/openstackclient/network/v2/network_rbac.py
index 4984e89d56..692a43857d 100644
--- a/openstackclient/network/v2/network_rbac.py
+++ b/openstackclient/network/v2/network_rbac.py
@@ -21,6 +21,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -90,7 +91,7 @@ def _get_attrs(client_manager, parsed_args):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateNetworkRBAC(command.ShowOne):
+class CreateNetworkRBAC(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create network RBAC policy")
 
     def get_parser(self, prog_name):
@@ -150,6 +151,8 @@ class CreateNetworkRBAC(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_rbac_policy(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns)
@@ -253,7 +256,7 @@ class ListNetworkRBAC(command.Lister):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetNetworkRBAC(command.Command):
+class SetNetworkRBAC(common.NeutronCommandWithExtraArgs):
     _description = _("Set network RBAC policy properties")
 
     def get_parser(self, prog_name):
@@ -291,6 +294,8 @@ class SetNetworkRBAC(command.Command):
                 parsed_args.target_project_domain,
             ).id
             attrs['target_tenant'] = project_id
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         client.update_rbac_policy(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/network_segment.py b/openstackclient/network/v2/network_segment.py
index c1a672e2d5..14a8edabe5 100644
--- a/openstackclient/network/v2/network_segment.py
+++ b/openstackclient/network/v2/network_segment.py
@@ -20,6 +20,7 @@ from osc_lib import exceptions
 from osc_lib import utils
 
 from openstackclient.i18n import _
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -30,7 +31,8 @@ def _get_columns(item):
     return sdk_utils.get_osc_show_columns_for_sdk_resource(item, {})
 
 
-class CreateNetworkSegment(command.ShowOne):
+class CreateNetworkSegment(command.ShowOne,
+                           common.NeutronCommandWithExtraArgs):
     _description = _("Create new network segment")
 
     def get_parser(self, prog_name):
@@ -88,6 +90,8 @@ class CreateNetworkSegment(command.ShowOne):
             attrs['physical_network'] = parsed_args.physical_network
         if parsed_args.segment is not None:
             attrs['segmentation_id'] = parsed_args.segment
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_segment(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns)
@@ -189,7 +193,7 @@ class ListNetworkSegment(command.Lister):
                 ) for s in data))
 
 
-class SetNetworkSegment(command.Command):
+class SetNetworkSegment(common.NeutronCommandWithExtraArgs):
     _description = _("Set network segment properties")
 
     def get_parser(self, prog_name):
@@ -220,6 +224,8 @@ class SetNetworkSegment(command.Command):
             attrs['description'] = parsed_args.description
         if parsed_args.name is not None:
             attrs['name'] = parsed_args.name
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         client.update_segment(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/network_segment_range.py b/openstackclient/network/v2/network_segment_range.py
index 6229995aab..ee414407ee 100644
--- a/openstackclient/network/v2/network_segment_range.py
+++ b/openstackclient/network/v2/network_segment_range.py
@@ -25,6 +25,7 @@ from osc_lib import utils
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -87,7 +88,8 @@ def _update_additional_fields_from_props(columns, props):
     return props
 
 
-class CreateNetworkSegmentRange(command.ShowOne):
+class CreateNetworkSegmentRange(command.ShowOne,
+                                common.NeutronCommandWithExtraArgs):
     _description = _("Create new network segment range")
 
     def get_parser(self, prog_name):
@@ -209,6 +211,10 @@ class CreateNetworkSegmentRange(command.ShowOne):
 
         if parsed_args.physical_network:
             attrs['physical_network'] = parsed_args.physical_network
+
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         obj = network_client.create_network_segment_range(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns)
@@ -365,7 +371,7 @@ class ListNetworkSegmentRange(command.Lister):
         return headers, display_props
 
 
-class SetNetworkSegmentRange(command.Command):
+class SetNetworkSegmentRange(common.NeutronCommandWithExtraArgs):
     _description = _("Set network segment range properties")
 
     def get_parser(self, prog_name):
@@ -419,6 +425,8 @@ class SetNetworkSegmentRange(command.Command):
             attrs['minimum'] = parsed_args.minimum
         if parsed_args.maximum:
             attrs['maximum'] = parsed_args.maximum
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         network_client.update_network_segment_range(obj, **attrs)
 
 
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index 4feffc1df4..ecb2382a85 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -326,7 +326,7 @@ def _convert_extra_dhcp_options(parsed_args):
     return dhcp_options
 
 
-class CreatePort(command.ShowOne):
+class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a new port")
 
     def get_parser(self, prog_name):
@@ -501,6 +501,9 @@ class CreatePort(command.ShowOne):
             if parsed_args.tags:
                 attrs['tags'] = list(set(parsed_args.tags))
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         with common.check_missing_extension_if_error(
                 self.app.client_manager.network, attrs):
             obj = client.create_port(**attrs)
@@ -697,7 +700,7 @@ class ListPort(command.Lister):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetPort(command.Command):
+class SetPort(common.NeutronCommandWithExtraArgs):
     _description = _("Set port properties")
 
     def get_parser(self, prog_name):
@@ -871,6 +874,9 @@ class SetPort(command.Command):
         if parsed_args.data_plane_status:
             attrs['data_plane_status'] = parsed_args.data_plane_status
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             with common.check_missing_extension_if_error(
                     self.app.client_manager.network, attrs):
@@ -902,7 +908,7 @@ class ShowPort(command.ShowOne):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class UnsetPort(command.Command):
+class UnsetPort(common.NeutronUnsetCommandWithExtraArgs):
     _description = _("Unset port properties")
 
     def get_parser(self, prog_name):
@@ -1023,6 +1029,9 @@ class UnsetPort(command.Command):
         if parsed_args.numa_policy:
             attrs['numa_affinity_policy'] = None
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_port(obj, **attrs)
 
diff --git a/openstackclient/network/v2/router.py b/openstackclient/network/v2/router.py
index e3e8accd21..d15300a0b7 100644
--- a/openstackclient/network/v2/router.py
+++ b/openstackclient/network/v2/router.py
@@ -27,6 +27,7 @@ from osc_lib.utils import tags as _tag
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -256,7 +257,7 @@ class RemoveExtraRoutesFromRouter(command.ShowOne):
 
 # TODO(yanxing'an): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateRouter(command.ShowOne):
+class CreateRouter(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a new router")
 
     def get_parser(self, prog_name):
@@ -332,6 +333,9 @@ class CreateRouter(command.ShowOne):
             attrs['ha'] = True
         if parsed_args.no_ha:
             attrs['ha'] = False
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         obj = client.create_router(**attrs)
         # tags cannot be set when created, so tags need to be set later.
         _tag.update_tags_for_set(client, obj, parsed_args)
@@ -576,7 +580,7 @@ class RemoveSubnetFromRouter(command.Command):
 
 # TODO(yanxing'an): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetRouter(command.Command):
+class SetRouter(common.NeutronCommandWithExtraArgs):
     _description = _("Set router properties")
 
     def get_parser(self, prog_name):
@@ -767,6 +771,10 @@ class SetRouter(command.Command):
 
         if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
             attrs['external_gateway_info']['qos_policy_id'] = None
+
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_router(obj, **attrs)
         # tags is a subresource and it needs to be updated separately.
@@ -809,7 +817,7 @@ class ShowRouter(command.ShowOne):
         return (display_columns, data)
 
 
-class UnsetRouter(command.Command):
+class UnsetRouter(common.NeutronUnsetCommandWithExtraArgs):
     _description = _("Unset router properties")
 
     def get_parser(self, prog_name):
@@ -875,6 +883,10 @@ class UnsetRouter(command.Command):
 
         if parsed_args.external_gateway:
             attrs['external_gateway_info'] = {}
+
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_router(obj, **attrs)
         # tags is a subresource and it needs to be updated separately.
diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py
index 0732c23edc..49dc14e403 100644
--- a/openstackclient/network/v2/security_group.py
+++ b/openstackclient/network/v2/security_group.py
@@ -95,7 +95,8 @@ def _get_columns(item):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateSecurityGroup(common.NetworkAndComputeShowOne):
+class CreateSecurityGroup(common.NetworkAndComputeShowOne,
+                          common.NeutronCommandWithExtraArgs):
     _description = _("Create a new security group")
 
     def update_parser_common(self, parser):
@@ -160,6 +161,8 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne):
                 parsed_args.project_domain,
             ).id
             attrs['tenant_id'] = project_id
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
 
         # Create the security group and display the results.
         obj = client.create_security_group(**attrs)
@@ -310,7 +313,8 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
                 ) for s in data))
 
 
-class SetSecurityGroup(common.NetworkAndComputeCommand):
+class SetSecurityGroup(common.NetworkAndComputeCommand,
+                       common.NeutronCommandWithExtraArgs):
     _description = _("Set security group properties")
 
     def update_parser_common(self, parser):
@@ -362,6 +366,8 @@ class SetSecurityGroup(common.NetworkAndComputeCommand):
             attrs['stateful'] = True
         if parsed_args.stateless:
             attrs['stateful'] = False
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         # NOTE(rtheis): Previous behavior did not raise a CommandError
         # if there were no updates. Maintain this behavior and issue
         # the update.
diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py
index 17241ed256..e273ded3d6 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -104,7 +104,8 @@ def _is_icmp_protocol(protocol):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
+class CreateSecurityGroupRule(common.NetworkAndComputeShowOne,
+                              common.NeutronCommandWithExtraArgs):
     _description = _("Create a new security group rule")
 
     def update_parser_common(self, parser):
@@ -355,6 +356,9 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
             ).id
             attrs['tenant_id'] = project_id
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         # Create and show the security group rule.
         obj = client.create_security_group_rule(**attrs)
         display_columns, columns = _get_columns(obj)
diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py
index eccdd4e460..09fd7c7c39 100644
--- a/openstackclient/network/v2/subnet.py
+++ b/openstackclient/network/v2/subnet.py
@@ -26,6 +26,7 @@ from osc_lib.utils import tags as _tag
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -250,7 +251,7 @@ def _get_attrs(client_manager, parsed_args, is_create=True):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateSubnet(command.ShowOne):
+class CreateSubnet(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create a subnet")
 
     def get_parser(self, prog_name):
@@ -373,6 +374,8 @@ class CreateSubnet(command.ShowOne):
     def take_action(self, parsed_args):
         client = self.app.client_manager.network
         attrs = _get_attrs(self.app.client_manager, parsed_args)
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_subnet(**attrs)
         # tags cannot be set when created, so tags need to be set later.
         _tag.update_tags_for_set(client, obj, parsed_args)
@@ -545,7 +548,7 @@ class ListSubnet(command.Lister):
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetSubnet(command.Command):
+class SetSubnet(common.NeutronCommandWithExtraArgs):
     _description = _("Set subnet properties")
 
     def get_parser(self, prog_name):
@@ -630,6 +633,8 @@ class SetSubnet(command.Command):
             attrs['allocation_pools'] = []
         if 'service_types' in attrs:
             attrs['service_types'] += obj.service_types
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         if attrs:
             client.update_subnet(obj, **attrs)
         # tags is a subresource and it needs to be updated separately.
@@ -657,7 +662,7 @@ class ShowSubnet(command.ShowOne):
         return (display_columns, data)
 
 
-class UnsetSubnet(command.Command):
+class UnsetSubnet(common.NeutronUnsetCommandWithExtraArgs):
     _description = _("Unset subnet properties")
 
     def get_parser(self, prog_name):
@@ -744,6 +749,9 @@ class UnsetSubnet(command.Command):
             _update_arguments(attrs['service_types'],
                               parsed_args.service_types,
                               'service-type')
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_subnet(obj, **attrs)
 
diff --git a/openstackclient/network/v2/subnet_pool.py b/openstackclient/network/v2/subnet_pool.py
index 56cf61526c..bdf7aba805 100644
--- a/openstackclient/network/v2/subnet_pool.py
+++ b/openstackclient/network/v2/subnet_pool.py
@@ -24,6 +24,7 @@ from osc_lib.utils import tags as _tag
 
 from openstackclient.i18n import _
 from openstackclient.identity import common as identity_common
+from openstackclient.network import common
 from openstackclient.network import sdk_utils
 
 
@@ -146,7 +147,7 @@ def _add_default_options(parser):
 
 # TODO(rtheis): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class CreateSubnetPool(command.ShowOne):
+class CreateSubnetPool(command.ShowOne, common.NeutronCommandWithExtraArgs):
     _description = _("Create subnet pool")
 
     def get_parser(self, prog_name):
@@ -203,6 +204,8 @@ class CreateSubnetPool(command.ShowOne):
         # NeutronServer expects prefixes to be a List
         if "prefixes" not in attrs:
             attrs['prefixes'] = []
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
         obj = client.create_subnet_pool(**attrs)
         # tags cannot be set when created, so tags need to be set later.
         _tag.update_tags_for_set(client, obj, parsed_args)
@@ -351,7 +354,7 @@ class ListSubnetPool(command.Lister):
 
 # TODO(rtheis): Use the SDK resource mapped attribute names once the
 # OSC minimum requirements include SDK 1.0.
-class SetSubnetPool(command.Command):
+class SetSubnetPool(common.NeutronCommandWithExtraArgs):
     _description = _("Set subnet pool properties")
 
     def get_parser(self, prog_name):
@@ -408,6 +411,9 @@ class SetSubnetPool(command.Command):
         if 'prefixes' in attrs:
             attrs['prefixes'].extend(obj.prefixes)
 
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+
         if attrs:
             client.update_subnet_pool(obj, **attrs)
         # tags is a subresource and it needs to be updated separately.
diff --git a/openstackclient/tests/unit/network/test_common.py b/openstackclient/tests/unit/network/test_common.py
index cde321aa23..4dde1b2bea 100644
--- a/openstackclient/tests/unit/network/test_common.py
+++ b/openstackclient/tests/unit/network/test_common.py
@@ -102,6 +102,27 @@ class FakeNetworkAndComputeShowOne(common.NetworkAndComputeShowOne):
         return client.compute_action(parsed_args)
 
 
+class FakeCreateNeutronCommandWithExtraArgs(
+        common.NeutronCommandWithExtraArgs):
+
+    def get_parser(self, prog_name):
+        parser = super(FakeCreateNeutronCommandWithExtraArgs,
+                       self).get_parser(prog_name)
+        parser.add_argument(
+            '--known-attribute',
+        )
+        return parser
+
+    def take_action(self, parsed_args):
+        client = self.app.client_manager.network
+        attrs = {}
+        if 'known_attribute' in parsed_args:
+            attrs['known_attribute'] = parsed_args.known_attribute
+        attrs.update(
+            self._parse_extra_properties(parsed_args.extra_properties))
+        client.test_create_action(**attrs)
+
+
 class TestNetworkAndCompute(utils.TestCommand):
 
     def setUp(self):
@@ -187,3 +208,121 @@ class TestNetworkAndComputeShowOne(TestNetworkAndCompute):
             m_action.side_effect = openstack.exceptions.HttpException("bar")
             self.assertRaisesRegex(exceptions.CommandError, "bar",
                                    self.cmd.take_action, mock.Mock())
+
+
+class TestNeutronCommandWithExtraArgs(utils.TestCommand):
+
+    def setUp(self):
+        super(TestNeutronCommandWithExtraArgs, self).setUp()
+
+        self.namespace = argparse.Namespace()
+
+        self.app.client_manager.network = mock.Mock()
+        self.network = self.app.client_manager.network
+        self.network.test_create_action = mock.Mock()
+
+        # Subclasses can override the command object to test.
+        self.cmd = FakeCreateNeutronCommandWithExtraArgs(
+            self.app, self.namespace)
+
+    def test_create_extra_attributes_default_type(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'name=extra_name,value=extra_value'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'value': 'extra_value'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value', extra_name='extra_value')
+
+    def test_create_extra_attributes_string(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'type=str,name=extra_name,value=extra_value'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'type': 'str',
+                                   'value': 'extra_value'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value', extra_name='extra_value')
+
+    def test_create_extra_attributes_bool(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'type=bool,name=extra_name,value=TrUe'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'type': 'bool',
+                                   'value': 'TrUe'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value', extra_name=True)
+
+    def test_create_extra_attributes_int(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'type=int,name=extra_name,value=8'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'type': 'int',
+                                   'value': '8'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value', extra_name=8)
+
+    def test_create_extra_attributes_list(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'type=list,name=extra_name,value=v_1;v_2'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'type': 'list',
+                                   'value': 'v_1;v_2'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value', extra_name=['v_1', 'v_2'])
+
+    def test_create_extra_attributes_dict(self):
+        arglist = [
+            '--known-attribute', 'known-value',
+            '--extra-property', 'type=dict,name=extra_name,value=n1:v1;n2:v2'
+        ]
+        verifylist = [
+            ('known_attribute', 'known-value'),
+            ('extra_properties', [{'name': 'extra_name',
+                                   'type': 'dict',
+                                   'value': 'n1:v1;n2:v2'}])
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        self.cmd.take_action(parsed_args)
+        self.network.test_create_action.assert_called_with(
+            known_attribute='known-value',
+            extra_name={'n1': 'v1', 'n2': 'v2'})
diff --git a/openstackclient/tests/unit/network/test_utils.py b/openstackclient/tests/unit/network/test_utils.py
new file mode 100644
index 0000000000..6252d7f766
--- /dev/null
+++ b/openstackclient/tests/unit/network/test_utils.py
@@ -0,0 +1,59 @@
+#   Licensed under the Apache License, Version 2.0 (the "License"); you may
+#   not use this file except in compliance with the License. You may obtain
+#   a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#   License for the specific language governing permissions and limitations
+#   under the License.
+#
+
+from osc_lib import exceptions
+
+from openstackclient.network import utils
+from openstackclient.tests.unit import utils as tests_utils
+
+
+class TestUtils(tests_utils.TestCase):
+
+    def test_str2bool(self):
+        self.assertTrue(utils.str2bool("true"))
+        self.assertTrue(utils.str2bool("True"))
+        self.assertTrue(utils.str2bool("TRUE"))
+        self.assertTrue(utils.str2bool("TrUe"))
+
+        self.assertFalse(utils.str2bool("false"))
+        self.assertFalse(utils.str2bool("False"))
+        self.assertFalse(utils.str2bool("FALSE"))
+        self.assertFalse(utils.str2bool("FaLsE"))
+        self.assertFalse(utils.str2bool("Something else"))
+        self.assertFalse(utils.str2bool(""))
+
+        self.assertIsNone(utils.str2bool(None))
+
+    def test_str2list(self):
+        self.assertEqual(
+            ['a', 'b', 'c'], utils.str2list("a;b;c"))
+        self.assertEqual(
+            ['abc'], utils.str2list("abc"))
+
+        self.assertEqual([], utils.str2list(""))
+        self.assertEqual([], utils.str2list(None))
+
+    def test_str2dict(self):
+        self.assertEqual(
+            {'a': 'aaa', 'b': '2'},
+            utils.str2dict('a:aaa;b:2'))
+        self.assertEqual(
+            {'a': 'aaa;b;c', 'd': 'ddd'},
+            utils.str2dict('a:aaa;b;c;d:ddd'))
+
+        self.assertEqual({}, utils.str2dict(""))
+        self.assertEqual({}, utils.str2dict(None))
+
+        self.assertRaises(
+            exceptions.CommandError,
+            utils.str2dict, "aaa;b:2")
diff --git a/requirements.txt b/requirements.txt
index d3a17e9a48..0ac991da20 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0
 
 cliff>=3.5.0 # Apache-2.0
 iso8601>=0.1.11 # MIT
-openstacksdk>=0.53.0 # Apache-2.0
+openstacksdk>=0.56.0 # Apache-2.0
 osc-lib>=2.3.0 # Apache-2.0
 oslo.i18n>=3.15.3 # Apache-2.0
 oslo.utils>=3.33.0 # Apache-2.0