diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index e305c331516b..a265e05ad253 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -1085,6 +1085,7 @@ enum ovs_action_attr {
 	OVS_ACTION_ATTR_CLONE,        /* Nested OVS_CLONE_ATTR_*.  */
 	OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
 	OVS_ACTION_ATTR_ADD_MPLS,     /* struct ovs_action_add_mpls. */
+	OVS_ACTION_ATTR_DEC_TTL,      /* Nested OVS_DEC_TTL_ATTR_*. */
 
 #ifndef __KERNEL__
 	OVS_ACTION_ATTR_TUNNEL_PUSH,   /* struct ovs_action_push_tnl*/
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 0b623fcea457..4124ce094aba 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -9244,6 +9244,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
     case OVS_ACTION_ATTR_CHECK_PKT_LEN:
     case OVS_ACTION_ATTR_DROP:
     case OVS_ACTION_ATTR_ADD_MPLS:
+    case OVS_ACTION_ATTR_DEC_TTL:
     case __OVS_ACTION_ATTR_MAX:
         OVS_NOT_REACHED();
     }
diff --git a/lib/dpif.c b/lib/dpif.c
index d07241f1e7cd..0f480bec48d0 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1289,6 +1289,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
     case OVS_ACTION_ATTR_CHECK_PKT_LEN:
     case OVS_ACTION_ATTR_DROP:
     case OVS_ACTION_ATTR_ADD_MPLS:
+    case OVS_ACTION_ATTR_DEC_TTL:
     case __OVS_ACTION_ATTR_MAX:
         OVS_NOT_REACHED();
     }
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 37f0f717af61..865b6cc0ec1e 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -833,6 +833,7 @@ requires_datapath_assistance(const struct nlattr *a)
     case OVS_ACTION_ATTR_CT_CLEAR:
     case OVS_ACTION_ATTR_CHECK_PKT_LEN:
     case OVS_ACTION_ATTR_ADD_MPLS:
+    case OVS_ACTION_ATTR_DEC_TTL:
     case OVS_ACTION_ATTR_DROP:
         return false;
 
@@ -1223,6 +1224,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
         case OVS_ACTION_ATTR_RECIRC:
         case OVS_ACTION_ATTR_CT:
         case OVS_ACTION_ATTR_UNSPEC:
+        case OVS_ACTION_ATTR_DEC_TTL:
         case __OVS_ACTION_ATTR_MAX:
         /* The following actions are handled by the scalar implementation. */
         case OVS_ACTION_ATTR_POP_VLAN:
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 3eb2c3cb98ca..42dbbb4cb26a 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -143,6 +143,7 @@ odp_action_len(uint16_t type)
     case OVS_ACTION_ATTR_POP_NSH: return 0;
     case OVS_ACTION_ATTR_CHECK_PKT_LEN: return ATTR_LEN_VARIABLE;
     case OVS_ACTION_ATTR_ADD_MPLS: return sizeof(struct ovs_action_add_mpls);
+    case OVS_ACTION_ATTR_DEC_TTL: return ATTR_LEN_VARIABLE;
     case OVS_ACTION_ATTR_DROP: return sizeof(uint32_t);
 
     case OVS_ACTION_ATTR_UNSPEC:
@@ -1130,6 +1131,25 @@ format_odp_check_pkt_len_action(struct ds *ds, const struct nlattr *attr,
     ds_put_cstr(ds, "))");
 }
 
+static void
+format_dec_ttl_action(struct ds *ds, const struct nlattr *attr,
+                      const struct hmap *portno_names)
+{
+    const struct nlattr *a;
+    unsigned int left;
+
+    ds_put_cstr(ds,"dec_ttl(le_1(");
+    NL_ATTR_FOR_EACH (a, left,
+                      nl_attr_get(attr), nl_attr_get_size(attr)) {
+        if (nl_attr_type(a) == OVS_ACTION_ATTR_DEC_TTL) {
+           format_odp_actions(ds, nl_attr_get(a),
+                              nl_attr_get_size(a), portno_names);
+           break;
+        }
+    }
+    ds_put_format(ds, "))");
+}
+
 static void
 format_odp_action(struct ds *ds, const struct nlattr *a,
                   const struct hmap *portno_names)
@@ -1283,6 +1303,9 @@ format_odp_action(struct ds *ds, const struct nlattr *a,
                       ntohs(mpls->mpls_ethertype));
         break;
     }
+    case OVS_ACTION_ATTR_DEC_TTL:
+        format_dec_ttl_action(ds, a, portno_names);
+        break;
     case OVS_ACTION_ATTR_DROP:
         ds_put_cstr(ds, "drop");
         break;
diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
index e6c2968f7e90..cd65dae7e18a 100644
--- a/ofproto/ofproto-dpif-ipfix.c
+++ b/ofproto/ofproto-dpif-ipfix.c
@@ -3135,6 +3135,7 @@ dpif_ipfix_read_actions(const struct flow *flow,
         case OVS_ACTION_ATTR_UNSPEC:
         case OVS_ACTION_ATTR_DROP:
         case OVS_ACTION_ATTR_ADD_MPLS:
+        case OVS_ACTION_ATTR_DEC_TTL:
         case __OVS_ACTION_ATTR_MAX:
         default:
             break;
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index a3c83bac8152..4a68e9b949b5 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -1236,6 +1236,7 @@ dpif_sflow_read_actions(const struct flow *flow,
         case OVS_ACTION_ATTR_CHECK_PKT_LEN:
         case OVS_ACTION_ATTR_DROP:
         case OVS_ACTION_ATTR_ADD_MPLS:
+        case OVS_ACTION_ATTR_DEC_TTL:
         case __OVS_ACTION_ATTR_MAX:
         default:
             break;
