@@ -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
------------
@@ -7277,6 +7277,11 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id,
ovs_mutex_unlock(&dp->meters_lock);
+ if (netdev_is_flow_api_enabled()) {
+ meter_offload_set(dpif_normalize_type(dpif_type(dpif)),
+ meter_id, config);
+ }
+
return 0;
}
@@ -7287,7 +7292,7 @@ dpif_netdev_meter_get(const struct dpif *dpif,
{
struct dp_netdev *dp = get_dp_netdev(dpif);
uint32_t meter_id = meter_id_.uint32;
- const struct dp_meter *meter;
+ struct dp_meter *meter;
if (meter_id >= MAX_METERS) {
return EFBIG;
@@ -7313,8 +7318,21 @@ dpif_netdev_meter_get(const struct dpif *dpif,
ovs_mutex_unlock(&meter->lock);
stats->n_bands = i;
- }
+ if (netdev_is_flow_api_enabled()) {
+ meter_offload_get(dpif_normalize_type(dpif_type(dpif)),
+ meter_id_, stats);
+
+ meter->packet_count = stats->packet_in_count;
+ meter->byte_count = stats->byte_in_count;
+
+ /* nit: Meter offload currently only supports one band */
+ if (meter->n_bands) {
+ stats->bands[0].packet_count = stats->packet_in_count;
+ stats->bands[0].byte_count = stats->byte_in_count;
+ }
+ }
+ }
return 0;
}
@@ -7330,6 +7348,11 @@ dpif_netdev_meter_del(struct dpif *dpif,
if (!error) {
uint32_t meter_id = meter_id_.uint32;
+ if (netdev_is_flow_api_enabled()) {
+ meter_offload_del(dpif_normalize_type(dpif_type(dpif)),
+ meter_id_, stats);
+ }
+
ovs_mutex_lock(&dp->meters_lock);
dp_meter_detach_free(&dp->meters, meter_id);
ovs_mutex_unlock(&dp->meters_lock);
@@ -4249,7 +4249,8 @@ dpif_netlink_meter_set(struct dpif *dpif_, ofproto_meter_id meter_id,
err = dpif_netlink_meter_set__(dpif_, meter_id, config);
if (!err && netdev_is_flow_api_enabled()) {
- meter_offload_set(meter_id, config);
+ meter_offload_set(dpif_normalize_type(dpif_type(dpif_)),
+ meter_id, config);
}
return err;
@@ -4348,7 +4349,8 @@ dpif_netlink_meter_get(const struct dpif *dpif, ofproto_meter_id meter_id,
err = dpif_netlink_meter_get_stats(dpif, meter_id, stats, max_bands,
OVS_METER_CMD_GET);
if (!err && netdev_is_flow_api_enabled()) {
- meter_offload_get(meter_id, stats);
+ meter_offload_get(dpif_normalize_type(dpif_type(dpif)),
+ meter_id, stats);
}
return err;
@@ -4363,7 +4365,8 @@ dpif_netlink_meter_del(struct dpif *dpif, ofproto_meter_id meter_id,
err = dpif_netlink_meter_get_stats(dpif, meter_id, stats,
max_bands, OVS_METER_CMD_DEL);
if (!err && netdev_is_flow_api_enabled()) {
- meter_offload_del(meter_id, stats);
+ meter_offload_del(dpif_normalize_type(dpif_type(dpif)),
+ meter_id, stats);
}
return err;
@@ -99,7 +99,8 @@ struct netdev_flow_api {
* returned.
*
* The meter id specified through 'config->meter_id' is ignored. */
- int (*meter_set)(ofproto_meter_id meter_id,
+ int (*meter_set)(const char *type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_config *config);
/* Queries HW for meter stats with the given 'meter_id'. Store the stats
@@ -110,7 +111,8 @@ struct netdev_flow_api {
* 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,
+ int (*meter_get)(const char *type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats);
/* Removes meter 'meter_id' from HW. Store the stats of dropped packets to
@@ -118,7 +120,8 @@ struct netdev_flow_api {
*
* '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,
+ int (*meter_del)(const char *type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats);
/* Initializies the netdev flow api.
@@ -2892,7 +2892,8 @@ meter_free_police_index(uint32_t police_index)
}
static int
-meter_tc_set_policer(ofproto_meter_id meter_id,
+meter_tc_set_policer(const char *dpif_type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_config *config)
{
uint32_t police_index;
@@ -2900,6 +2901,11 @@ meter_tc_set_policer(ofproto_meter_id meter_id,
bool add_policer;
int err;
+ if (strcmp(dpif_type, "system")) {
+ VLOG_DBG("meter doesn't belongs to the system datapath. Skipping.");
+ return EOPNOTSUPP;
+ }
+
if (!config->bands || config->n_bands < 1 ||
config->bands[0].type != OFPMBT13_DROP) {
return 0;
@@ -2946,12 +2952,18 @@ meter_tc_set_policer(ofproto_meter_id meter_id,
}
static int
-meter_tc_get_policer(ofproto_meter_id meter_id,
+meter_tc_get_policer(const char *dpif_type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats)
{
uint32_t police_index;
int err = ENOENT;
+ if (strcmp(dpif_type, "system")) {
+ VLOG_DBG("meter doesn't belongs to the system datapath. Skipping.");
+ return EOPNOTSUPP;
+ }
+
if (!meter_id_lookup(meter_id.uint32, &police_index)) {
err = tc_get_policer_action(police_index, stats);
if (err) {
@@ -2965,12 +2977,18 @@ meter_tc_get_policer(ofproto_meter_id meter_id,
}
static int
-meter_tc_del_policer(ofproto_meter_id meter_id,
+meter_tc_del_policer(const char *dpif_type,
+ ofproto_meter_id meter_id,
struct ofputil_meter_stats *stats)
{
uint32_t police_index;
int err = ENOENT;
+ if (strcmp(dpif_type, "system")) {
+ VLOG_DBG("meter doesn't belongs to the system datapath. Skipping.");
+ return EOPNOTSUPP;
+ }
+
if (!meter_id_lookup(meter_id.uint32, &police_index)) {
err = tc_del_policer_action(police_index, stats);
if (err && err != ENOENT) {
@@ -199,14 +199,15 @@ netdev_assign_flow_api(struct netdev *netdev)
}
void
-meter_offload_set(ofproto_meter_id meter_id,
+meter_offload_set(const char *dpif_type,
+ 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);
+ int ret = rfa->flow_api->meter_set(dpif_type, 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,
@@ -219,13 +220,15 @@ meter_offload_set(ofproto_meter_id meter_id,
}
int
-meter_offload_get(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
+meter_offload_get(const char *dpif_type,
+ 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);
+ int ret = rfa->flow_api->meter_get(dpif_type, 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,
@@ -238,13 +241,15 @@ meter_offload_get(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
}
int
-meter_offload_del(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
+meter_offload_del(const char *dpif_type,
+ 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);
+ int ret = rfa->flow_api->meter_del(dpif_type, 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,
@@ -158,9 +158,12 @@ 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 *);
+void meter_offload_set(const char *dpif_type, ofproto_meter_id,
+ struct ofputil_meter_config *);
+int meter_offload_get(const char *dpif_type, ofproto_meter_id,
+ struct ofputil_meter_stats *);
+int meter_offload_del(const char *dpif_type, ofproto_meter_id,
+ struct ofputil_meter_stats *);
#ifdef __cplusplus
}