diff --git a/doc/source/command-objects/port.rst b/doc/source/command-objects/port.rst
index ddfbb445b3..b3f4c7f9fd 100644
--- a/doc/source/command-objects/port.rst
+++ b/doc/source/command-objects/port.rst
@@ -30,6 +30,7 @@ Create new port
         [--security-group <security-group> | --no-security-group]
         [--dns-name <dns-name>]
         [--allowed-address ip-address=<ip-address>[,mac-address=<mac-address>]]
+        [--qos-policy <qos-policy>]
         [--project <project> [--project-domain <project-domain>]]
         [--enable-port-security | --disable-port-security]
         <name>
@@ -104,6 +105,10 @@ Create new port
     ip-address=<ip-address>[,mac-address=<mac-address>]
     (repeat option to set multiple allowed-address pairs)
 
+.. option:: --qos-policy <qos-policy>
+
+    Attach QoS policy to this port (name or ID)
+
 .. option:: --project <project>
 
     Owner's project (name or ID)
@@ -217,6 +222,7 @@ Set port properties
         [--binding-profile <binding-profile>]
         [--no-binding-profile]
         [--host <host-id>]
+        [--qos-policy <qos-policy>]
         [--enable | --disable]
         [--name <name>]
         [--mac-address <mac-address>]
@@ -274,6 +280,10 @@ Set port properties
 
     Allocate port on host ``<host-id>`` (ID only)
 
+.. option:: --qos-policy <qos-policy>
+
+    Attach QoS policy to this port (name or ID)
+
 .. option:: --enable
 
     Enable port
@@ -359,6 +369,7 @@ Unset port properties
         [--binding-profile <binding-profile-key> [...]]
         [--security-group <security-group> [...]]
         [--allowed-address ip-address=<ip-address>[,mac-address=<mac-address>] [...]]
+        [--qos-policy]
         <port>
 
 .. option:: --fixed-ip subnet=<subnet>,ip-address=<ip-address>
@@ -383,6 +394,10 @@ Unset port properties
     ip-address=<ip-address>[,mac-address=<mac-address>]
     (repeat option to unset multiple allowed-address pairs)
 
+.. option:: --qos-policy
+
+    Remove the QoS policy attached to the port
+
 .. _port_unset-port:
 .. describe:: <port>
 
diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index 9d598fabec..3a32916b78 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -155,6 +155,13 @@ def _get_attrs(client_manager, parsed_args):
     if parsed_args.enable_port_security:
         attrs['port_security_enabled'] = True
 
+    if 'no_qos_policy' in parsed_args and parsed_args.no_qos_policy:
+        attrs['qos_policy_id'] = None
+
+    if parsed_args.qos_policy:
+        attrs['qos_policy_id'] = client_manager.network.find_qos_policy(
+            parsed_args.qos_policy, ignore_missing=False).id
+
     return attrs
 
 
@@ -337,7 +344,7 @@ class CreatePort(command.ShowOne):
             help=_("Name of this port")
         )
         # TODO(singhj): Add support for extended options:
-        # qos,dhcp
+        # dhcp
         secgroups = parser.add_mutually_exclusive_group()
         secgroups.add_argument(
             '--security-group',
@@ -353,6 +360,11 @@ class CreatePort(command.ShowOne):
             action='store_true',
             help=_("Associate no security groups with this port")
         )
+        parser.add_argument(
+            '--qos-policy',
+            metavar='<qos-policy>',
+            help=_("Attach QoS policy to this port (name or ID)")
+        )
         port_security = parser.add_mutually_exclusive_group()
         port_security.add_argument(
             '--enable-port-security',
@@ -403,6 +415,9 @@ class CreatePort(command.ShowOne):
             attrs['allowed_address_pairs'] = (
                 _convert_address_pairs(parsed_args))
 
+        if parsed_args.qos_policy:
+            attrs['qos_policy_id'] = client.find_qos_policy(
+                parsed_args.qos_policy, ignore_missing=False).id
         obj = client.create_port(**attrs)
         display_columns, columns = _get_columns(obj)
         data = utils.get_item_properties(obj, columns, formatters=_formatters)
@@ -619,6 +634,11 @@ class SetPort(command.Command):
                    "Specify both --binding-profile and --no-binding-profile "
                    "to overwrite the current binding:profile information.")
         )
+        parser.add_argument(
+            '--qos-policy',
+            metavar='<qos-policy>',
+            help=_("Attach QoS policy to this port (name or ID)")
+        )
         parser.add_argument(
             'port',
             metavar="<port>",
@@ -675,8 +695,8 @@ class SetPort(command.Command):
         client = self.app.client_manager.network
 
         _prepare_fixed_ips(self.app.client_manager, parsed_args)
-        attrs = _get_attrs(self.app.client_manager, parsed_args)
         obj = client.find_port(parsed_args.port, ignore_missing=False)
+        attrs = _get_attrs(self.app.client_manager, parsed_args)
 
         if parsed_args.no_binding_profile:
             attrs['binding:profile'] = {}
@@ -794,6 +814,12 @@ class UnsetPort(command.Command):
                    "[,mac-address=<mac-address>] (repeat option to set "
                    "multiple allowed-address pairs)")
         )
+        parser.add_argument(
+            '--qos-policy',
+            action='store_true',
+            default=False,
+            help=_("Remove the QoS policy attached to the port")
+        )
 
         return parser
 
@@ -843,6 +869,8 @@ class UnsetPort(command.Command):
                 msg = _("Port does not contain allowed-address-pair %s") % addr
                 raise exceptions.CommandError(msg)
             attrs['allowed_address_pairs'] = tmp_addr_pairs
+        if parsed_args.qos_policy:
+            attrs['qos_policy_id'] = None
 
         if attrs:
             client.update_port(obj, **attrs)
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index d3685409a1..9a2899419c 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -572,6 +572,7 @@ class FakePort(object):
             'security_group_ids': [],
             'status': 'ACTIVE',
             'tenant_id': 'project-id-' + uuid.uuid4().hex,
+            'qos_policy_id': 'qos-policy-id-' + uuid.uuid4().hex,
         }
 
         # Overwrite default attributes.
@@ -590,6 +591,7 @@ class FakePort(object):
         port.is_port_security_enabled = port_attrs['port_security_enabled']
         port.project_id = port_attrs['tenant_id']
         port.security_group_ids = port_attrs['security_group_ids']
+        port.qos_policy_id = port_attrs['qos_policy_id']
 
         return port
 
diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py
index 701af8790b..851bf25ad2 100644
--- a/openstackclient/tests/unit/network/v2/test_port.py
+++ b/openstackclient/tests/unit/network/v2/test_port.py
@@ -57,6 +57,7 @@ class TestPort(network_fakes.TestNetworkV2):
             'network_id',
             'port_security_enabled',
             'project_id',
+            'qos_policy_id',
             'security_group_ids',
             'status',
         )
@@ -82,6 +83,7 @@ class TestPort(network_fakes.TestNetworkV2):
             fake_port.network_id,
             fake_port.port_security_enabled,
             fake_port.project_id,
+            fake_port.qos_policy_id,
             utils.format_list(fake_port.security_group_ids),
             fake_port.status,
         )
@@ -422,6 +424,35 @@ class TestCreatePort(TestPort):
         self.assertEqual(ref_columns, columns)
         self.assertEqual(ref_data, data)
 
+    def test_create_port_with_qos(self):
+        qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
+        self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
+        arglist = [
+            '--network', self._port.network_id,
+            '--qos-policy', qos_policy.id,
+            'test-port',
+        ]
+        verifylist = [
+            ('network', self._port.network_id,),
+            ('enable', True),
+            ('qos_policy', qos_policy.id),
+            ('name', 'test-port'),
+        ]
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        columns, data = (self.cmd.take_action(parsed_args))
+
+        self.network.create_port.assert_called_once_with(**{
+            'admin_state_up': True,
+            'network_id': self._port.network_id,
+            'qos_policy_id': qos_policy.id,
+            'name': 'test-port',
+        })
+
+        ref_columns, ref_data = self._get_common_cols_data(self._port)
+        self.assertEqual(ref_columns, columns)
+        self.assertEqual(ref_data, data)
+
     def test_create_port_security_enabled(self):
         arglist = [
             '--network', self._port.network_id,
@@ -1316,6 +1347,30 @@ class TestSetPort(TestPort):
             'port_security_enabled': False,
         })
 
+    def test_set_port_with_qos(self):
+        qos_policy = network_fakes.FakeNetworkQosPolicy.create_one_qos_policy()
+        self.network.find_qos_policy = mock.Mock(return_value=qos_policy)
+        _testport = network_fakes.FakePort.create_one_port(
+            {'qos_policy_id': None})
+        self.network.find_port = mock.Mock(return_value=_testport)
+        arglist = [
+            '--qos-policy', qos_policy.id,
+            _testport.name,
+        ]
+        verifylist = [
+            ('qos_policy', qos_policy.id),
+            ('port', _testport.name),
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        result = self.cmd.take_action(parsed_args)
+
+        attrs = {
+            'qos_policy_id': qos_policy.id,
+        }
+        self.network.update_port.assert_called_once_with(_testport, **attrs)
+        self.assertIsNone(result)
+
 
 class TestShowPort(TestPort):
 
@@ -1379,6 +1434,7 @@ class TestUnsetPort(TestPort):
             '--fixed-ip',
             'subnet=042eb10a-3a18-4658-ab-cf47c8d03152,ip-address=1.0.0.0',
             '--binding-profile', 'Superman',
+            '--qos-policy',
             self._testport.name,
         ]
         verifylist = [
@@ -1386,6 +1442,7 @@ class TestUnsetPort(TestPort):
                 'subnet': '042eb10a-3a18-4658-ab-cf47c8d03152',
                 'ip-address': '1.0.0.0'}]),
             ('binding_profile', ['Superman']),
+            ('qos_policy', True),
         ]
 
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -1395,7 +1452,8 @@ class TestUnsetPort(TestPort):
             'fixed_ips': [{
                 'subnet_id': '042eb10a-3a18-4658-ab-cf47c8d03152',
                 'ip_address': '0.0.0.1'}],
-            'binding:profile': {'batman': 'Joker'}
+            'binding:profile': {'batman': 'Joker'},
+            'qos_policy_id': None
         }
         self.network.update_port.assert_called_once_with(
             self._testport, **attrs)
diff --git a/releasenotes/notes/bug-1612136-ec240349a933db12.yaml b/releasenotes/notes/bug-1612136-ec240349a933db12.yaml
new file mode 100644
index 0000000000..42872966b5
--- /dev/null
+++ b/releasenotes/notes/bug-1612136-ec240349a933db12.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Add ``--qos-policy`` option to ``port create``,  ``port set`` and
+    ``port unset`` commands.
+    [Bug `1612136 <https://bugs.launchpad.net/python-openstackclient/+bug/1612136>`_]