diff mbox series

[ovs-dev,v4,7/9] features: Add detection for sample with registers.

Message ID 20240731090520.342643-8-dceara@redhat.com
State Changes Requested
Headers show
Series Add ACL Sampling using per-flow IPFIX. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Dumitru Ceara July 31, 2024, 9:05 a.m. UTC
From: Ales Musil <amusil@redhat.com>

Add detection for sample action that allows to configure
obs_domain_id and obs_point_id via registers. This feature
is available only from OvS version 3.4.

Signed-off-by: Ales Musil <amusil@redhat.com>
---
 controller/chassis.c      | 10 +++++
 include/ovn/features.h    |  3 ++
 lib/features.c            | 91 +++++++++++++++++++++++++++++++++++++++
 northd/en-global-config.c | 10 +++++
 northd/en-global-config.h |  1 +
 5 files changed, 115 insertions(+)

Comments

Dumitru Ceara July 31, 2024, 9:16 a.m. UTC | #1
On 7/31/24 11:05, Dumitru Ceara wrote:
> From: Ales Musil <amusil@redhat.com>
> 
> Add detection for sample action that allows to configure
> obs_domain_id and obs_point_id via registers. This feature
> is available only from OvS version 3.4.
> 
> Signed-off-by: Ales Musil <amusil@redhat.com>
> ---

Acked-by: Dumitru Ceara <dceara@redhat.com>
Ilya Maximets July 31, 2024, 10:38 a.m. UTC | #2
On 7/31/24 11:05, Dumitru Ceara wrote:
> From: Ales Musil <amusil@redhat.com>
> 
> Add detection for sample action that allows to configure
> obs_domain_id and obs_point_id via registers. This feature
> is available only from OvS version 3.4.
> 
> Signed-off-by: Ales Musil <amusil@redhat.com>
> ---
>  controller/chassis.c      | 10 +++++
>  include/ovn/features.h    |  3 ++
>  lib/features.c            | 91 +++++++++++++++++++++++++++++++++++++++
>  northd/en-global-config.c | 10 +++++
>  northd/en-global-config.h |  1 +
>  5 files changed, 115 insertions(+)
> 
> diff --git a/controller/chassis.c b/controller/chassis.c
> index 4942ba281d..1aa51b9d6c 100644
> --- a/controller/chassis.c
> +++ b/controller/chassis.c
> @@ -372,6 +372,9 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
>      smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
>      smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
>      smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
> +    bool sample = ovs_feature_is_supported(OVS_DP_SAMPLE_REG_SUPPORT);
> +    smap_replace(config, OVN_FEATURE_SAMPLE_WITH_REGISTERS,
> +                 sample ? "true" : "false");
>  }
>  
>  /*
> @@ -523,6 +526,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
>          return true;
>      }
>  
> +    if (!smap_get_bool(&chassis_rec->other_config,
> +                       OVN_FEATURE_SAMPLE_WITH_REGISTERS,
> +                       false)) {
> +        return true;
> +    }
> +
>      return false;
>  }
>  
> @@ -656,6 +665,7 @@ update_supported_sset(struct sset *supported)
>      sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
>      sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
>      sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
> +    sset_add(supported, OVN_FEATURE_SAMPLE_WITH_REGISTERS);
>  }
>  
>  static void
> diff --git a/include/ovn/features.h b/include/ovn/features.h
> index 7b67b2f777..5c90a36450 100644
> --- a/include/ovn/features.h
> +++ b/include/ovn/features.h
> @@ -29,6 +29,7 @@
>  #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
>  #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
>  #define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
> +#define OVN_FEATURE_SAMPLE_WITH_REGISTERS "ovn-sample-with-registers"
>  
>  /* OVS datapath supported features.  Based on availability OVN might generate
>   * different types of openflows.
> @@ -39,6 +40,7 @@ enum ovs_feature_support_bits {
>      OVS_CT_TUPLE_FLUSH_BIT,
>      OVS_DP_HASH_L4_SYM_BIT,
>      OVS_DP_GROUP_SUPPORT_BIT,
> +    OVS_DP_SAMPLE_REG_SUPPORT_BIT,
>  };
>  
>  enum ovs_feature_value {
> @@ -47,6 +49,7 @@ enum ovs_feature_value {
>      OVS_CT_TUPLE_FLUSH_SUPPORT = (1 << OVS_CT_TUPLE_FLUSH_BIT),
>      OVS_DP_HASH_L4_SYM_SUPPORT = (1 << OVS_DP_HASH_L4_SYM_BIT),
>      OVS_DP_GROUP_SUPPORT = (1 << OVS_DP_GROUP_SUPPORT_BIT),
> +    OVS_DP_SAMPLE_REG_SUPPORT = (1 << OVS_DP_SAMPLE_REG_SUPPORT_BIT),

Same here.  The 'DP' part makes no sense as this is feature has
nothing to do with the datapath implementation.

Best regards, Ilya Maximets.
Ilya Maximets July 31, 2024, 10:45 a.m. UTC | #3
On 7/31/24 12:38, Ilya Maximets wrote:
> On 7/31/24 11:05, Dumitru Ceara wrote:
>> From: Ales Musil <amusil@redhat.com>
>>
>> Add detection for sample action that allows to configure
>> obs_domain_id and obs_point_id via registers. This feature
>> is available only from OvS version 3.4.
>>
>> Signed-off-by: Ales Musil <amusil@redhat.com>
>> ---
>>  controller/chassis.c      | 10 +++++
>>  include/ovn/features.h    |  3 ++
>>  lib/features.c            | 91 +++++++++++++++++++++++++++++++++++++++
>>  northd/en-global-config.c | 10 +++++
>>  northd/en-global-config.h |  1 +
>>  5 files changed, 115 insertions(+)
>>
>> diff --git a/controller/chassis.c b/controller/chassis.c
>> index 4942ba281d..1aa51b9d6c 100644
>> --- a/controller/chassis.c
>> +++ b/controller/chassis.c
>> @@ -372,6 +372,9 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
>>      smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
>> +    bool sample = ovs_feature_is_supported(OVS_DP_SAMPLE_REG_SUPPORT);
>> +    smap_replace(config, OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>> +                 sample ? "true" : "false");
>>  }
>>  
>>  /*
>> @@ -523,6 +526,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
>>          return true;
>>      }
>>  
>> +    if (!smap_get_bool(&chassis_rec->other_config,
>> +                       OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>> +                       false)) {
>> +        return true;
>> +    }

Also, this doesn't look right.  Unlike other features, this one
is conditional.  So, chassis_other_config_changed() will always
return 'true' if OVS doesn't support the feature.

>> +
>>      return false;
>>  }
>>  
>> @@ -656,6 +665,7 @@ update_supported_sset(struct sset *supported)
>>      sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
>> +    sset_add(supported, OVN_FEATURE_SAMPLE_WITH_REGISTERS);
>>  }
>>  
>>  static void
>> diff --git a/include/ovn/features.h b/include/ovn/features.h
>> index 7b67b2f777..5c90a36450 100644
>> --- a/include/ovn/features.h
>> +++ b/include/ovn/features.h
>> @@ -29,6 +29,7 @@
>>  #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
>>  #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
>>  #define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
>> +#define OVN_FEATURE_SAMPLE_WITH_REGISTERS "ovn-sample-with-registers"
>>  
>>  /* OVS datapath supported features.  Based on availability OVN might generate
>>   * different types of openflows.
>> @@ -39,6 +40,7 @@ enum ovs_feature_support_bits {
>>      OVS_CT_TUPLE_FLUSH_BIT,
>>      OVS_DP_HASH_L4_SYM_BIT,
>>      OVS_DP_GROUP_SUPPORT_BIT,
>> +    OVS_DP_SAMPLE_REG_SUPPORT_BIT,
>>  };
>>  
>>  enum ovs_feature_value {
>> @@ -47,6 +49,7 @@ enum ovs_feature_value {
>>      OVS_CT_TUPLE_FLUSH_SUPPORT = (1 << OVS_CT_TUPLE_FLUSH_BIT),
>>      OVS_DP_HASH_L4_SYM_SUPPORT = (1 << OVS_DP_HASH_L4_SYM_BIT),
>>      OVS_DP_GROUP_SUPPORT = (1 << OVS_DP_GROUP_SUPPORT_BIT),
>> +    OVS_DP_SAMPLE_REG_SUPPORT = (1 << OVS_DP_SAMPLE_REG_SUPPORT_BIT),
> 
> Same here.  The 'DP' part makes no sense as this is feature has
> nothing to do with the datapath implementation.
> 
> Best regards, Ilya Maximets.
Dumitru Ceara July 31, 2024, 12:14 p.m. UTC | #4
On 7/31/24 12:45, Ilya Maximets wrote:
> On 7/31/24 12:38, Ilya Maximets wrote:
>> On 7/31/24 11:05, Dumitru Ceara wrote:
>>> From: Ales Musil <amusil@redhat.com>
>>>
>>> Add detection for sample action that allows to configure
>>> obs_domain_id and obs_point_id via registers. This feature
>>> is available only from OvS version 3.4.
>>>
>>> Signed-off-by: Ales Musil <amusil@redhat.com>
>>> ---
>>>  controller/chassis.c      | 10 +++++
>>>  include/ovn/features.h    |  3 ++
>>>  lib/features.c            | 91 +++++++++++++++++++++++++++++++++++++++
>>>  northd/en-global-config.c | 10 +++++
>>>  northd/en-global-config.h |  1 +
>>>  5 files changed, 115 insertions(+)
>>>
>>> diff --git a/controller/chassis.c b/controller/chassis.c
>>> index 4942ba281d..1aa51b9d6c 100644
>>> --- a/controller/chassis.c
>>> +++ b/controller/chassis.c
>>> @@ -372,6 +372,9 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
>>>      smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
>>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
>>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
>>> +    bool sample = ovs_feature_is_supported(OVS_DP_SAMPLE_REG_SUPPORT);
>>> +    smap_replace(config, OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>>> +                 sample ? "true" : "false");
>>>  }
>>>  
>>>  /*
>>> @@ -523,6 +526,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
>>>          return true;
>>>      }
>>>  
>>> +    if (!smap_get_bool(&chassis_rec->other_config,
>>> +                       OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>>> +                       false)) {
>>> +        return true;
>>> +    }
> 
> Also, this doesn't look right.  Unlike other features, this one
> is conditional.  So, chassis_other_config_changed() will always
> return 'true' if OVS doesn't support the feature.
> 

Good point, this needs fixing.

>>> +
>>>      return false;
>>>  }
>>>  
>>> @@ -656,6 +665,7 @@ update_supported_sset(struct sset *supported)
>>>      sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
>>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
>>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
>>> +    sset_add(supported, OVN_FEATURE_SAMPLE_WITH_REGISTERS);
>>>  }
>>>  
>>>  static void
>>> diff --git a/include/ovn/features.h b/include/ovn/features.h
>>> index 7b67b2f777..5c90a36450 100644
>>> --- a/include/ovn/features.h
>>> +++ b/include/ovn/features.h
>>> @@ -29,6 +29,7 @@
>>>  #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
>>>  #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
>>>  #define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
>>> +#define OVN_FEATURE_SAMPLE_WITH_REGISTERS "ovn-sample-with-registers"
>>>  
>>>  /* OVS datapath supported features.  Based on availability OVN might generate
>>>   * different types of openflows.
>>> @@ -39,6 +40,7 @@ enum ovs_feature_support_bits {
>>>      OVS_CT_TUPLE_FLUSH_BIT,
>>>      OVS_DP_HASH_L4_SYM_BIT,
>>>      OVS_DP_GROUP_SUPPORT_BIT,
>>> +    OVS_DP_SAMPLE_REG_SUPPORT_BIT,
>>>  };
>>>  
>>>  enum ovs_feature_value {
>>> @@ -47,6 +49,7 @@ enum ovs_feature_value {
>>>      OVS_CT_TUPLE_FLUSH_SUPPORT = (1 << OVS_CT_TUPLE_FLUSH_BIT),
>>>      OVS_DP_HASH_L4_SYM_SUPPORT = (1 << OVS_DP_HASH_L4_SYM_BIT),
>>>      OVS_DP_GROUP_SUPPORT = (1 << OVS_DP_GROUP_SUPPORT_BIT),
>>> +    OVS_DP_SAMPLE_REG_SUPPORT = (1 << OVS_DP_SAMPLE_REG_SUPPORT_BIT),
>>
>> Same here.  The 'DP' part makes no sense as this is feature has
>> nothing to do with the datapath implementation.
>>

FWIW, in my eyes, OVN's dataplane (datapath) is OVS so everything listed
here is datapath related from OVN's perspective.  But OK, for
CT_TUPLE_FLUSH we don't use the "DP" particle, I guess we can skip that
here too.

What name would make more sense to you?  OVS_SAMPLE_REG_SUPPORT?

>> Best regards, Ilya Maximets.
> 

Regards,
Dumitru
Ilya Maximets July 31, 2024, 12:25 p.m. UTC | #5
On 7/31/24 14:14, Dumitru Ceara wrote:
> On 7/31/24 12:45, Ilya Maximets wrote:
>> On 7/31/24 12:38, Ilya Maximets wrote:
>>> On 7/31/24 11:05, Dumitru Ceara wrote:
>>>> From: Ales Musil <amusil@redhat.com>
>>>>
>>>> Add detection for sample action that allows to configure
>>>> obs_domain_id and obs_point_id via registers. This feature
>>>> is available only from OvS version 3.4.
>>>>
>>>> Signed-off-by: Ales Musil <amusil@redhat.com>
>>>> ---
>>>>  controller/chassis.c      | 10 +++++
>>>>  include/ovn/features.h    |  3 ++
>>>>  lib/features.c            | 91 +++++++++++++++++++++++++++++++++++++++
>>>>  northd/en-global-config.c | 10 +++++
>>>>  northd/en-global-config.h |  1 +
>>>>  5 files changed, 115 insertions(+)
>>>>
>>>> diff --git a/controller/chassis.c b/controller/chassis.c
>>>> index 4942ba281d..1aa51b9d6c 100644
>>>> --- a/controller/chassis.c
>>>> +++ b/controller/chassis.c
>>>> @@ -372,6 +372,9 @@ chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
>>>>      smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
>>>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
>>>>      smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
>>>> +    bool sample = ovs_feature_is_supported(OVS_DP_SAMPLE_REG_SUPPORT);
>>>> +    smap_replace(config, OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>>>> +                 sample ? "true" : "false");
>>>>  }
>>>>  
>>>>  /*
>>>> @@ -523,6 +526,12 @@ chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
>>>>          return true;
>>>>      }
>>>>  
>>>> +    if (!smap_get_bool(&chassis_rec->other_config,
>>>> +                       OVN_FEATURE_SAMPLE_WITH_REGISTERS,
>>>> +                       false)) {
>>>> +        return true;
>>>> +    }
>>
>> Also, this doesn't look right.  Unlike other features, this one
>> is conditional.  So, chassis_other_config_changed() will always
>> return 'true' if OVS doesn't support the feature.
>>
> 
> Good point, this needs fixing.
> 
>>>> +
>>>>      return false;
>>>>  }
>>>>  
>>>> @@ -656,6 +665,7 @@ update_supported_sset(struct sset *supported)
>>>>      sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
>>>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
>>>>      sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
>>>> +    sset_add(supported, OVN_FEATURE_SAMPLE_WITH_REGISTERS);
>>>>  }
>>>>  
>>>>  static void
>>>> diff --git a/include/ovn/features.h b/include/ovn/features.h
>>>> index 7b67b2f777..5c90a36450 100644
>>>> --- a/include/ovn/features.h
>>>> +++ b/include/ovn/features.h
>>>> @@ -29,6 +29,7 @@
>>>>  #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
>>>>  #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
>>>>  #define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
>>>> +#define OVN_FEATURE_SAMPLE_WITH_REGISTERS "ovn-sample-with-registers"
>>>>  
>>>>  /* OVS datapath supported features.  Based on availability OVN might generate
>>>>   * different types of openflows.
>>>> @@ -39,6 +40,7 @@ enum ovs_feature_support_bits {
>>>>      OVS_CT_TUPLE_FLUSH_BIT,
>>>>      OVS_DP_HASH_L4_SYM_BIT,
>>>>      OVS_DP_GROUP_SUPPORT_BIT,
>>>> +    OVS_DP_SAMPLE_REG_SUPPORT_BIT,
>>>>  };
>>>>  
>>>>  enum ovs_feature_value {
>>>> @@ -47,6 +49,7 @@ enum ovs_feature_value {
>>>>      OVS_CT_TUPLE_FLUSH_SUPPORT = (1 << OVS_CT_TUPLE_FLUSH_BIT),
>>>>      OVS_DP_HASH_L4_SYM_SUPPORT = (1 << OVS_DP_HASH_L4_SYM_BIT),
>>>>      OVS_DP_GROUP_SUPPORT = (1 << OVS_DP_GROUP_SUPPORT_BIT),
>>>> +    OVS_DP_SAMPLE_REG_SUPPORT = (1 << OVS_DP_SAMPLE_REG_SUPPORT_BIT),
>>>
>>> Same here.  The 'DP' part makes no sense as this is feature has
>>> nothing to do with the datapath implementation.
>>>
> 
> FWIW, in my eyes, OVN's dataplane (datapath) is OVS so everything listed
> here is datapath related from OVN's perspective.  But OK, for
> CT_TUPLE_FLUSH we don't use the "DP" particle, I guess we can skip that
> here too.
> 
> What name would make more sense to you?  OVS_SAMPLE_REG_SUPPORT?

Sounds fine.

> 
>>> Best regards, Ilya Maximets.
>>
> 
> Regards,
> Dumitru
>
diff mbox series

Patch

diff --git a/controller/chassis.c b/controller/chassis.c
index 4942ba281d..1aa51b9d6c 100644
--- a/controller/chassis.c
+++ b/controller/chassis.c
@@ -372,6 +372,9 @@  chassis_build_other_config(const struct ovs_chassis_cfg *ovs_cfg,
     smap_replace(config, OVN_FEATURE_LS_DPG_COLUMN, "true");
     smap_replace(config, OVN_FEATURE_CT_COMMIT_NAT_V2, "true");
     smap_replace(config, OVN_FEATURE_CT_COMMIT_TO_ZONE, "true");
+    bool sample = ovs_feature_is_supported(OVS_DP_SAMPLE_REG_SUPPORT);
+    smap_replace(config, OVN_FEATURE_SAMPLE_WITH_REGISTERS,
+                 sample ? "true" : "false");
 }
 
 /*
@@ -523,6 +526,12 @@  chassis_other_config_changed(const struct ovs_chassis_cfg *ovs_cfg,
         return true;
     }
 
+    if (!smap_get_bool(&chassis_rec->other_config,
+                       OVN_FEATURE_SAMPLE_WITH_REGISTERS,
+                       false)) {
+        return true;
+    }
+
     return false;
 }
 
@@ -656,6 +665,7 @@  update_supported_sset(struct sset *supported)
     sset_add(supported, OVN_FEATURE_LS_DPG_COLUMN);
     sset_add(supported, OVN_FEATURE_CT_COMMIT_NAT_V2);
     sset_add(supported, OVN_FEATURE_CT_COMMIT_TO_ZONE);
+    sset_add(supported, OVN_FEATURE_SAMPLE_WITH_REGISTERS);
 }
 
 static void
diff --git a/include/ovn/features.h b/include/ovn/features.h
index 7b67b2f777..5c90a36450 100644
--- a/include/ovn/features.h
+++ b/include/ovn/features.h
@@ -29,6 +29,7 @@ 
 #define OVN_FEATURE_LS_DPG_COLUMN "ls-dpg-column"
 #define OVN_FEATURE_CT_COMMIT_NAT_V2 "ct-commit-nat-v2"
 #define OVN_FEATURE_CT_COMMIT_TO_ZONE "ct-commit-to-zone"
+#define OVN_FEATURE_SAMPLE_WITH_REGISTERS "ovn-sample-with-registers"
 
 /* OVS datapath supported features.  Based on availability OVN might generate
  * different types of openflows.
@@ -39,6 +40,7 @@  enum ovs_feature_support_bits {
     OVS_CT_TUPLE_FLUSH_BIT,
     OVS_DP_HASH_L4_SYM_BIT,
     OVS_DP_GROUP_SUPPORT_BIT,
+    OVS_DP_SAMPLE_REG_SUPPORT_BIT,
 };
 
 enum ovs_feature_value {
@@ -47,6 +49,7 @@  enum ovs_feature_value {
     OVS_CT_TUPLE_FLUSH_SUPPORT = (1 << OVS_CT_TUPLE_FLUSH_BIT),
     OVS_DP_HASH_L4_SYM_SUPPORT = (1 << OVS_DP_HASH_L4_SYM_BIT),
     OVS_DP_GROUP_SUPPORT = (1 << OVS_DP_GROUP_SUPPORT_BIT),
+    OVS_DP_SAMPLE_REG_SUPPORT = (1 << OVS_DP_SAMPLE_REG_SUPPORT_BIT),
 };
 
 void ovs_feature_support_destroy(void);
diff --git a/lib/features.c b/lib/features.c
index f8682cf360..6caf654374 100644
--- a/lib/features.c
+++ b/lib/features.c
@@ -25,6 +25,8 @@ 
 #include "openvswitch/vlog.h"
 #include "openvswitch/ofpbuf.h"
 #include "openvswitch/rconn.h"
+#include "openvswitch/ofp-actions.h"
+#include "openvswitch/ofp-bundle.h"
 #include "openvswitch/ofp-msgs.h"
 #include "openvswitch/ofp-meter.h"
 #include "openvswitch/ofp-group.h"
@@ -185,6 +187,87 @@  group_features_handle_response(struct ovs_openflow_feature *feature,
     return supported_ovs_features & feature->value;
 }
 
+static void
+sample_with_reg_send_request(struct ovs_openflow_feature *feature)
+{
+    struct ofputil_bundle_ctrl_msg ctrl = {
+        .bundle_id = 0,
+        .flags     = OFPBF_ORDERED | OFPBF_ATOMIC,
+        .type      = OFPBCT_OPEN_REQUEST,
+    };
+    rconn_send(swconn,
+               ofputil_encode_bundle_ctrl_request(OFP15_VERSION, &ctrl), NULL);
+
+    uint8_t actions_stub[64];
+    struct ofpbuf actions;
+    ofpbuf_use_stub(&actions, actions_stub, sizeof(actions_stub));
+
+    struct mf_subfield subfield = {
+        .field = mf_from_id(MFF_REG0),
+        .n_bits = 32,
+        .ofs = 0
+    };
+
+    struct ofpact_sample *sample = ofpact_put_SAMPLE(&actions);
+    sample->probability = UINT16_MAX;
+    sample->collector_set_id = 0;
+    sample->obs_domain_src = subfield;
+    sample->obs_point_src = subfield;
+    sample->sampling_port = OFPP_NONE;
+
+    struct ofputil_flow_mod fm = {
+        .priority = 0,
+        .table_id = 0,
+        .ofpacts = actions.data,
+        .ofpacts_len = actions.size,
+        .command = OFPFC_ADD,
+        .new_cookie = htonll(0),
+        .buffer_id = UINT32_MAX,
+        .out_port = OFPP_ANY,
+        .out_group = OFPG_ANY,
+    };
+
+    struct match match;
+    match_init_catchall(&match);
+    minimatch_init(&fm.match, &match);
+
+    struct ofpbuf *fm_msg = ofputil_encode_flow_mod(&fm, OFPUTIL_P_OF15_OXM);
+
+    struct ofputil_bundle_add_msg bam = {
+        .bundle_id = ctrl.bundle_id,
+        .flags = ctrl.flags,
+        .msg = fm_msg->data,
+    };
+    struct ofpbuf *msg = ofputil_encode_bundle_add(OFP15_VERSION, &bam);
+
+    feature->xid = ((struct ofp_header *) msg->data)->xid;
+    rconn_send(swconn, msg, NULL);
+
+    ctrl.type = OFPBCT_DISCARD_REQUEST;
+    rconn_send(swconn,
+               ofputil_encode_bundle_ctrl_request(OFP15_VERSION, &ctrl), NULL);
+
+    minimatch_destroy(&fm.match);
+    ofpbuf_delete(fm_msg);
+}
+
+static bool
+sample_with_reg_handle_response(struct ovs_openflow_feature *feature,
+                                enum ofptype type, const struct ofp_header *oh)
+{
+    if (type != OFPTYPE_ERROR) {
+        log_unexpected_reply(feature, oh);
+    }
+
+    return false;
+}
+
+static bool
+sample_with_reg_handle_barrier(struct ovs_openflow_feature *feature OVS_UNUSED)
+{
+    return true;
+}
+
 static struct ovs_openflow_feature all_openflow_features[] = {
         {
             .value = OVS_DP_METER_SUPPORT,
@@ -199,6 +282,13 @@  static struct ovs_openflow_feature all_openflow_features[] = {
             .send_request = group_features_send_request,
             .handle_response = group_features_handle_response,
             .handle_barrier = default_barrier_response_handle,
+        },
+        {
+            .value = OVS_DP_SAMPLE_REG_SUPPORT,
+            .name = "sample_action_with_registers",
+            .send_request = sample_with_reg_send_request,
+            .handle_response = sample_with_reg_handle_response,
+            .handle_barrier = sample_with_reg_handle_barrier,
         }
 };
 
@@ -271,6 +361,7 @@  ovs_feature_is_valid(enum ovs_feature_value feature)
     case OVS_CT_TUPLE_FLUSH_SUPPORT:
     case OVS_DP_HASH_L4_SYM_SUPPORT:
     case OVS_DP_GROUP_SUPPORT:
+    case OVS_DP_SAMPLE_REG_SUPPORT:
         return true;
     default:
         return false;
diff --git a/northd/en-global-config.c b/northd/en-global-config.c
index d7607aa074..0ce7f83083 100644
--- a/northd/en-global-config.c
+++ b/northd/en-global-config.c
@@ -381,6 +381,7 @@  northd_enable_all_features(struct ed_type_global_config *data)
         .ls_dpg_column = true,
         .ct_commit_nat_v2 = true,
         .ct_commit_to_zone = true,
+        .sample_with_reg = true,
     };
 }
 
@@ -442,6 +443,15 @@  build_chassis_features(const struct sbrec_chassis_table *sbrec_chassis_table,
             chassis_features->ct_commit_to_zone) {
             chassis_features->ct_commit_to_zone = false;
         }
+
+        bool sample_with_reg =
+                smap_get_bool(&chassis->other_config,
+                              OVN_FEATURE_SAMPLE_WITH_REGISTERS,
+                              false);
+        if (!sample_with_reg &&
+            chassis_features->sample_with_reg) {
+            chassis_features->sample_with_reg = false;
+        }
     }
 }
 
diff --git a/northd/en-global-config.h b/northd/en-global-config.h
index 8a1c35fc8f..0cf34482af 100644
--- a/northd/en-global-config.h
+++ b/northd/en-global-config.h
@@ -19,6 +19,7 @@  struct chassis_features {
     bool ls_dpg_column;
     bool ct_commit_nat_v2;
     bool ct_commit_to_zone;
+    bool sample_with_reg;
 };
 
 struct global_config_tracked_data {