diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index a3b650d38050..185d8acbc9a3 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1025,7 +1025,8 @@ classify_upcall(enum dpif_upcall_type type, const struct nlattr *userdata)
 static void
 compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
                   const struct flow *flow, odp_port_t odp_in_port,
-                  struct ofpbuf *buf)
+                  struct ofpbuf *buf, uint32_t slowpath_meter_id,
+                  uint32_t controller_meter_id)
 {
     union user_action_cookie cookie;
     odp_port_t port;
@@ -1039,8 +1040,28 @@ compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
         ? ODPP_NONE
         : odp_in_port;
     pid = dpif_port_get_pid(udpif->dpif, port, flow_hash_5tuple(flow, 0));
+
+    size_t offset;
+    size_t ac_offset;
+    uint32_t meter_id = xout->slow & SLOW_CONTROLLER ? controller_meter_id
+                                                     : slowpath_meter_id;
+
+    if (meter_id != UINT32_MAX) {
+        /* If slowpath meter is configured, generate clone(meter, userspace)
+         * action.   */
+        offset = nl_msg_start_nested(buf, OVS_ACTION_ATTR_SAMPLE);
+        nl_msg_put_u32(buf, OVS_SAMPLE_ATTR_PROBABILITY, UINT32_MAX);
+        ac_offset = nl_msg_start_nested(buf, OVS_SAMPLE_ATTR_ACTIONS);
+        nl_msg_put_u32(buf, OVS_ACTION_ATTR_METER, meter_id);
+    }
+
     odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path,
                              ODPP_NONE, false, buf);
+
+    if (meter_id != UINT32_MAX) {
+        nl_msg_end_nested(buf, ac_offset);
+        nl_msg_end_nested(buf, offset);
+    }
 }
 
 /* If there is no error, the upcall must be destroyed with upcall_uninit()
@@ -1143,10 +1164,12 @@ upcall_xlate(struct udpif *udpif, struct upcall *upcall,
         ofpbuf_use_const(&upcall->put_actions,
                          odp_actions->data, odp_actions->size);
     } else {
+        uint32_t smid = upcall->ofproto->up.slowpath_meter_id;
+        uint32_t cmid = upcall->ofproto->up.controller_meter_id;
         /* upcall->put_actions already initialized by upcall_receive(). */
         compose_slow_path(udpif, &upcall->xout, upcall->flow,
                           upcall->flow->in_port.odp_port,
-                          &upcall->put_actions);
+                          &upcall->put_actions, smid, cmid);
     }
 
     /* This function is also called for slow-pathed flows.  As we are only
@@ -1972,9 +1995,14 @@ revalidate_ukey__(struct udpif *udpif, const struct udpif_key *ukey,
     }
 
     if (xoutp->slow) {
+        struct ofproto_dpif *ofproto;
+        ofproto = xlate_lookup_ofproto(udpif->backer, &ctx.flow, NULL);
+        uint32_t smid= ofproto->up.slowpath_meter_id;
+        uint32_t cmid= ofproto->up.controller_meter_id;
+
         ofpbuf_clear(odp_actions);
         compose_slow_path(udpif, xoutp, &ctx.flow, ctx.flow.in_port.odp_port,
-                          odp_actions);
+                          odp_actions, smid, cmid);
     }
 
     if (odp_flow_key_to_mask(ukey->mask, ukey->mask_len, &dp_mask, &ctx.flow)
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 22cb533b57bb..06c4e3bbf5f8 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -1658,6 +1658,44 @@ NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len
 vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x1234
 ])
 
+AT_CHECK([ovs-appctl revalidator/purge])
+AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
+
+dnl Add a controller meter.
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=controller pktps stats bands=type=drop rate=1'])
+
+dnl Advance time by 1 second.
+AT_CHECK([ovs-appctl time/warp 1000], [0], [ignore])
+
+for i in `seq 1 8`; do
+    AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x4321)'])
+done
+
+AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
+flow-dump from non-dpdk interfaces:
+packets:7, bytes:98, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,slow_path(controller))))
+])
+
+AT_CHECK([ovs-appctl time/warp 1], [0], [ignore])
+OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+
+dnl Out of 8 packets we sent, one executes the controller action via
+dnl miss upcall. Another one got passed the rate limiter.
+dnl The rest of packets are blocked by the rate limiter.
+AT_CHECK([cat ofctl_monitor.log], [0], [dnl
+NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
+vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x4321
+NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=14 in_port=1 (via action) data_len=14 (unbuffered)
+vlan_tci=0x0000,dl_src=50:54:00:00:00:09,dl_dst=50:54:00:00:00:0a,dl_type=0x4321
+])
+dnl Check meter stats to make it gives the same picture;
+dnl 7 packets hit the meter, but 6 packets are dropped by band0.
+AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0], [0], [dnl
+OFPST_METER reply (OF1.3) (xid=0x2):
+meter:controller flow_count:0 packet_in_count:7 byte_in_count:98 duration:1.054s bands:
+0: packet_count:6 byte_count:84
+])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
