@@ -401,10 +401,11 @@ Supported actions for hardware offload are:
- Modification of IPv6 (set_field:<ADDR>->ipv6_src/ipv6_dst/mod_nw_ttl).
- Clone/output (tnl_push and output) for encapsulating over a tunnel.
- Tunnel pop, for packets received on physical ports.
+- Meter.
.. note::
- Tunnel offloads are experimental APIs in DPDK. In order to enable it,
- compile with -DALLOW_EXPERIMENTAL_API.
+ Tunnel offloads and Meter offloads are experimental APIs in DPDK. To enable
+ these features, compile with -DALLOW_EXPERIMENTAL_API.
Multiprocess
------------
@@ -102,6 +102,16 @@ struct netdev_flow_api {
int (*meter_set)(ofproto_meter_id meter_id,
struct ofputil_meter_config *config);
+ /* Offloads or modifies the offloaded meter on the netdev 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 converted as an
+ * internal meter id. */
+ int (*dpdk_meter_set)(struct netdev *,
+ ofproto_meter_id meter_id,
+ struct ofputil_meter_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.
@@ -113,6 +123,18 @@ struct netdev_flow_api {
int (*meter_get)(ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats);
+ /* Queries netdev 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 (*dpdk_meter_get)(struct netdev *,
+ ofproto_meter_id meter_id,
+ struct ofputil_meter_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.
*
@@ -121,6 +143,14 @@ struct netdev_flow_api {
int (*meter_del)(ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats);
+ /* Removes meter 'meter_id' from netdev. Store the stats of dropped packets
+ * to band 0. On failure, a non-zero error code is returned.
+ *
+ * If del success, 'stats' will be set zero. */
+ int (*dpdk_meter_del)(struct netdev *,
+ 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 *);
@@ -256,6 +256,65 @@ meter_offload_del(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
return 0;
}
+void
+dpdk_meter_offload_set(struct netdev *dev,
+ ofproto_meter_id meter_id,
+ struct ofputil_meter_config *config)
+{
+ struct netdev_registered_flow_api *rfa;
+
+ /* Offload APIs could fail, for example, because the offload is not
+ * supported. This is fine, as the offload API should take care of this. */
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->dpdk_meter_set) {
+ int ret = rfa->flow_api->dpdk_meter_set(dev, 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);
+ }
+ }
+ }
+}
+
+void
+dpdk_meter_offload_get(struct netdev *dev,
+ 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->dpdk_meter_get) {
+ int ret = rfa->flow_api->dpdk_meter_get(dev, 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);
+ }
+ }
+ }
+}
+
+void
+dpdk_meter_offload_del(struct netdev *dev,
+ 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->dpdk_meter_del) {
+ int ret = rfa->flow_api->dpdk_meter_del(dev, 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);
+ }
+ }
+ }
+}
+
int
netdev_flow_flush(struct netdev *netdev)
{
@@ -161,6 +161,15 @@ int netdev_ports_get_n_flows(const char *dpif_type,
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 *);
+void dpdk_meter_offload_set(struct netdev *,
+ ofproto_meter_id,
+ struct ofputil_meter_config *);
+void dpdk_meter_offload_get(struct netdev *,
+ ofproto_meter_id,
+ struct ofputil_meter_stats *);
+void dpdk_meter_offload_del(struct netdev *,
+ ofproto_meter_id,
+ struct ofputil_meter_stats *);
#ifdef __cplusplus
}