diff --git a/openstackclient/network/v2/port.py b/openstackclient/network/v2/port.py
index a21324ae27..8ea1077ab3 100644
--- a/openstackclient/network/v2/port.py
+++ b/openstackclient/network/v2/port.py
@@ -158,6 +158,16 @@ def _get_attrs(client_manager, parsed_args):
             parsed_args.disable_uplink_status_propagation):
         attrs['propagate_uplink_status'] = False
 
+    if ('numa_policy_required' in parsed_args and
+            parsed_args.numa_policy_required):
+        attrs['numa_affinity_policy'] = 'required'
+    elif ('numa_policy_preferred' in parsed_args and
+          parsed_args.numa_policy_preferred):
+        attrs['numa_affinity_policy'] = 'preferred'
+    elif ('numa_policy_legacy' in parsed_args and
+          parsed_args.numa_policy_legacy):
+        attrs['numa_affinity_policy'] = 'legacy'
+
     return attrs
 
 
@@ -265,6 +275,22 @@ def _add_updatable_args(parser):
         help=_("Set DNS name for this port "
                "(requires DNS integration extension)")
     )
+    numa_affinity_policy_group = parser.add_mutually_exclusive_group()
+    numa_affinity_policy_group.add_argument(
+        '--numa-policy-required',
+        action='store_true',
+        help=_("NUMA affinity policy required to schedule this port")
+    )
+    numa_affinity_policy_group.add_argument(
+        '--numa-policy-preferred',
+        action='store_true',
+        help=_("NUMA affinity policy preferred to schedule this port")
+    )
+    numa_affinity_policy_group.add_argument(
+        '--numa-policy-legacy',
+        action='store_true',
+        help=_("NUMA affinity policy using legacy mode to schedule this port")
+    )
 
 
 # TODO(abhiraut): Use the SDK resource mapped attribute names once the
@@ -904,6 +930,11 @@ class UnsetPort(command.Command):
             action='store_true',
             help=_("Clear existing information of data plane status")
         )
+        parser.add_argument(
+            '--numa-policy',
+            action='store_true',
+            help=_("Clear existing NUMA affinity policy")
+        )
 
         _tag.add_tag_option_to_parser_for_unset(parser, _('port'))
 
@@ -959,6 +990,8 @@ class UnsetPort(command.Command):
             attrs['qos_policy_id'] = None
         if parsed_args.data_plane_status:
             attrs['data_plane_status'] = None
+        if parsed_args.numa_policy:
+            attrs['numa_affinity_policy'] = 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 cef0a11c91..3df4042cba 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -634,6 +634,7 @@ class FakePort(object):
             'mac_address': 'fa:16:3e:a9:4e:72',
             'name': 'port-name-' + uuid.uuid4().hex,
             'network_id': 'network-id-' + uuid.uuid4().hex,
+            'numa_affinity_policy': 'required',
             'port_security_enabled': True,
             'security_group_ids': [],
             'status': 'ACTIVE',
diff --git a/openstackclient/tests/unit/network/v2/test_port.py b/openstackclient/tests/unit/network/v2/test_port.py
index 87aea61fac..70fa063dce 100644
--- a/openstackclient/tests/unit/network/v2/test_port.py
+++ b/openstackclient/tests/unit/network/v2/test_port.py
@@ -59,6 +59,7 @@ class TestPort(network_fakes.TestNetworkV2):
             'mac_address',
             'name',
             'network_id',
+            'numa_affinity_policy',
             'port_security_enabled',
             'project_id',
             'qos_network_policy_id',
@@ -90,6 +91,7 @@ class TestPort(network_fakes.TestNetworkV2):
             fake_port.mac_address,
             fake_port.name,
             fake_port.network_id,
+            fake_port.numa_affinity_policy,
             fake_port.port_security_enabled,
             fake_port.project_id,
             fake_port.qos_network_policy_id,
@@ -655,6 +657,50 @@ class TestCreatePort(TestPort):
             'name': 'test-port',
         })
 
+    def _test_create_with_numa_affinity_policy(self, policy=None):
+        arglist = [
+            '--network', self._port.network_id,
+            'test-port',
+        ]
+        if policy:
+            arglist += ['--numa-policy-%s' % policy]
+
+        numa_affinity_policy = None if not policy else policy
+        verifylist = [
+            ('network', self._port.network_id,),
+            ('name', 'test-port'),
+        ]
+        if policy:
+            verifylist.append(('numa_policy_%s' % policy, True))
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        columns, data = (self.cmd.take_action(parsed_args))
+
+        create_args = {
+            'admin_state_up': True,
+            'network_id': self._port.network_id,
+            'name': 'test-port',
+        }
+        if numa_affinity_policy:
+            create_args['numa_affinity_policy'] = numa_affinity_policy
+        self.network.create_port.assert_called_once_with(**create_args)
+
+        self.assertEqual(self.columns, columns)
+        self.assertItemEqual(self.data, data)
+
+    def test_create_with_numa_affinity_policy_required(self):
+        self._test_create_with_numa_affinity_policy(policy='required')
+
+    def test_create_with_numa_affinity_policy_preferred(self):
+        self._test_create_with_numa_affinity_policy(policy='preferred')
+
+    def test_create_with_numa_affinity_policy_legacy(self):
+        self._test_create_with_numa_affinity_policy(policy='legacy')
+
+    def test_create_with_numa_affinity_policy_null(self):
+        self._test_create_with_numa_affinity_policy()
+
 
 class TestDeletePort(TestPort):
 
@@ -1668,6 +1714,32 @@ class TestSetPort(TestPort):
     def test_set_with_no_tag(self):
         self._test_set_tags(with_tags=False)
 
+    def _test_create_with_numa_affinity_policy(self, policy):
+        arglist = [
+            '--numa-policy-%s' % policy,
+            self._port.id,
+        ]
+        verifylist = [
+            ('numa_policy_%s' % policy, True),
+            ('port', self._port.id,)
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+        self.cmd.take_action(parsed_args)
+
+        self.network.update_port.assert_called_once_with(
+            self._port, **{'numa_affinity_policy': policy})
+
+    def test_create_with_numa_affinity_policy_required(self):
+        self._test_create_with_numa_affinity_policy('required')
+
+    def test_create_with_numa_affinity_policy_preferred(self):
+        self._test_create_with_numa_affinity_policy('preferred')
+
+    def test_create_with_numa_affinity_policy_legacy(self):
+        self._test_create_with_numa_affinity_policy('legacy')
+
 
 class TestShowPort(TestPort):
 
@@ -1923,3 +1995,26 @@ class TestUnsetPort(TestPort):
 
     def test_unset_with_all_tag(self):
         self._test_unset_tags(with_tags=False)
+
+    def test_unset_numa_affinity_policy(self):
+        _fake_port = network_fakes.FakePort.create_one_port(
+            {'numa_affinity_policy': 'required'})
+        self.network.find_port = mock.Mock(return_value=_fake_port)
+        arglist = [
+            '--numa-policy',
+            _fake_port.name,
+        ]
+        verifylist = [
+            ('numa_policy', True),
+            ('port', _fake_port.name),
+        ]
+
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+        result = self.cmd.take_action(parsed_args)
+
+        attrs = {
+            'numa_affinity_policy': None,
+        }
+
+        self.network.update_port.assert_called_once_with(_fake_port, **attrs)
+        self.assertIsNone(result)
diff --git a/releasenotes/notes/add-port-numa-affinity-policy-4706b0f9485a5d4d.yaml b/releasenotes/notes/add-port-numa-affinity-policy-4706b0f9485a5d4d.yaml
new file mode 100644
index 0000000000..0fbc54b187
--- /dev/null
+++ b/releasenotes/notes/add-port-numa-affinity-policy-4706b0f9485a5d4d.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Add NUMA affinity policy to ``port create``, ``port set`` and
+    ``port unset`` commands.