@@ -94,6 +94,33 @@ struct netdev_flow_api {
* takes ownership of a packet if errno != EOPNOTSUPP. */
int (*hw_miss_packet_recover)(struct netdev *, struct dp_packet *);
+ /* Offloads or modifies the offloaded meter in HW with the given 'meter_id'
+ * and the configuration in 'config'. On failure, a non-zero error code is
+ * returned.
+ *
+ * The meter id specified through 'config->meter_id' is ignored. */
+ int (*meter_set)(ofproto_meter_id meter_id,
+ struct ofputil_meter_config *config);
+
+ /* Queries HW for meter stats with the given 'meter_id'. Store the stats
+ * of dropped packets to band 0. On failure, a non-zero error code is
+ * returned.
+ *
+ * Note that the 'stats' structure is already initialized, and only the
+ * available statistics should be incremented, not replaced. Those fields
+ * are packet_in_count, byte_in_count and band[]->byte_count and
+ * band[]->packet_count. */
+ int (*meter_get)(ofproto_meter_id meter_id,
+ struct ofputil_meter_stats *stats);
+
+ /* Removes meter 'meter_id' from HW. Store the stats of dropped packets to
+ * band 0. On failure, a non-zero error code is returned.
+ *
+ * 'stats' may be passed in as NULL if no stats are needed, See the above
+ * function for additional details on the 'stats' usage. */
+ int (*meter_del)(ofproto_meter_id meter_id,
+ struct ofputil_meter_stats *stats);
+
/* Initializies the netdev flow api.
* Return 0 if successful, otherwise returns a positive errno value. */
int (*init_flow_api)(struct netdev *);
@@ -58,6 +58,7 @@
VLOG_DEFINE_THIS_MODULE(netdev_offload);
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
static bool netdev_flow_api_enabled = false;
#define DEFAULT_OFFLOAD_THREAD_NB 1
@@ -195,6 +196,64 @@ netdev_assign_flow_api(struct netdev *netdev)
return -1;
}
+void
+meter_offload_set(ofproto_meter_id meter_id,
+ struct ofputil_meter_config *config)
+{
+ struct netdev_registered_flow_api *rfa;
+
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->meter_set) {
+ int ret = rfa->flow_api->meter_set(meter_id, config);
+ if (ret) {
+ VLOG_DBG_RL(&rl, "Failed setting meter %u for flow api %s, "
+ "error %d", meter_id.uint32, rfa->flow_api->type,
+ ret);
+ }
+ }
+ }
+ /* Offload APIs could fail, for example, because the offload is not
+ * supported. This is fine, as the offload API should take care of this. */
+}
+
+int
+meter_offload_get(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
+{
+ struct netdev_registered_flow_api *rfa;
+
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->meter_get) {
+ int ret = rfa->flow_api->meter_get(meter_id, stats);
+ if (ret) {
+ VLOG_DBG_RL(&rl, "Failed getting meter %u for flow api %s, "
+ "error %d", meter_id.uint32, rfa->flow_api->type,
+ ret);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+meter_offload_del(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
+{
+ struct netdev_registered_flow_api *rfa;
+
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->meter_del) {
+ int ret = rfa->flow_api->meter_del(meter_id, stats);
+ if (ret) {
+ VLOG_DBG_RL(&rl, "Failed deleting meter %u for flow api %s, "
+ "error %d", meter_id.uint32, rfa->flow_api->type,
+ ret);
+ }
+ }
+ }
+
+ return 0;
+}
+
int
netdev_flow_flush(struct netdev *netdev)
{
@@ -22,6 +22,7 @@
#include "openvswitch/types.h"
#include "ovs-rcu.h"
#include "ovs-thread.h"
+#include "openvswitch/ofp-meter.h"
#include "packets.h"
#include "flow.h"
@@ -158,6 +159,10 @@ int netdev_ports_flow_get(const char *dpif_type, struct match *match,
int netdev_ports_get_n_flows(const char *dpif_type,
odp_port_t port_no, uint64_t *n_flows);
+void meter_offload_set(ofproto_meter_id, struct ofputil_meter_config *);
+int meter_offload_get(ofproto_meter_id, struct ofputil_meter_stats *);
+int meter_offload_del(ofproto_meter_id, struct ofputil_meter_stats *);
+
#ifdef __cplusplus
}
#endif