@@ -62,7 +62,7 @@ int ofputil_decode_meter_config(struct ofpbuf *,
struct ofpbuf *bands);
void ofputil_format_meter_config(struct ds *,
const struct ofputil_meter_config *);
-uint32_t ofputil_meter_config_max_rate(struct ofputil_meter_config *conf);
+uint32_t *ofputil_meter_config_rate_burst(struct ofputil_meter_config *conf);
struct ofputil_meter_mod {
uint16_t command;
@@ -2773,16 +2773,6 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
return;
}
- VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:recirc %x mod %x \n", match->flow.recirc_id,
- match->flow.skb_priority);
- VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nw_src %x ct_nw_src %x \n",
- ntohl(match->flow.nw_src), ntohl(match->flow.ct_nw_src));
- VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat action %x \n",
- nat_action.nat_action);
- VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat min addr %x \n",
- ntohl(nat_action.min_addr.ipv4));
- VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat max addr %x \n",
- ntohl(nat_action.max_addr.ipv4));
if (ovsthread_once_start(&offload_thread_once)) {
xpthread_cond_init(&dp_flow_offload.cond, NULL);
ovs_thread_create("dp_netdev_flow_offload",
@@ -21,6 +21,7 @@
#include <rte_flow.h>
#include <rte_mtr.h>
+#include <rte_ethdev.h>
#include "cmap.h"
#include "dpif-netdev.h"
@@ -642,6 +643,16 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions)
ds_put_format(s, " Set-Jump to : %"PRIu32"\n", jump->group);
} else if (actions->type == RTE_FLOW_ACTION_TYPE_CT) {
ds_put_cstr(s, " Set-CT-enable bit\n");
+
+ } else if (actions->type == RTE_FLOW_ACTION_TYPE_METER) {
+ const struct rte_flow_action_meter *meter = actions->conf;
+
+ ds_put_cstr(s, "rte flow meter action:\n");
+ if (meter) {
+ ds_put_format(s, " Meter: %d\n", meter->mtr_id);
+ } else {
+ ds_put_cstr(s, " Meter = null\n");
+ }
} else {
ds_put_format(s, "unknown rte flow action (%d)\n", actions->type);
}
@@ -864,7 +875,6 @@ parse_geneve_match(struct flow_patterns *patterns,
uint8_t val = *(buf+i);
opt_data = opt_data | val ;
opt_data = (i==data_len-1)? opt_data: opt_data<< 8;
- VLOG_DBG("TIMO DBG. geneve op hdr =0x%08x",opt_data);
}
/* GENEVE option */
op_spec = xzalloc(sizeof *op_spec);
@@ -1162,8 +1172,6 @@ parse_flow_match(struct flow_patterns *patterns,
*next_proto_mask = 0;
}
}
- VLOG_DBG("TIMO DBG. ct_state mask =0x%04x,ct_state =0x%04x",
- match->wc.masks.ct_state, match->flow.ct_state);
/* ct state */
if (match->wc.masks.ct_state &&
(match->wc.masks.ct_state & match->flow.ct_state & CS_ESTABLISHED) ){
@@ -1186,13 +1194,25 @@ static void dpdk_meter_destroy(void *priv_data)
{
struct dpdk_meter_offload *dmo = priv_data;
struct rte_mtr_error mtr_error;
-
+ int ret;
+
if (dmo) {
- rte_mtr_meter_profile_delete(dmo->port_id,
+ ret = rte_mtr_meter_profile_delete(dmo->port_id,
dmo->mc.mtr_id,
&mtr_error);
- rte_mtr_destroy(dmo->port_id, dmo->mc.mtr_id,
+ if (ret && ret != -EEXIST) {
+ VLOG_ERR("rte_mtr_meter_profile_delete fail: err_type: %d err_msg: %s, portid: %d\n",
+ mtr_error.type, mtr_error.message, dmo->port_id);
+ }
+ VLOG_DBG("yunxiang_DBG:in dpdk_meter_destroy1, port_id is %d,mtr_id is %d", dmo->port_id, dmo->mc.mtr_id);
+
+ ret = rte_mtr_destroy(dmo->port_id, dmo->mc.mtr_id,
&mtr_error);
+ if (ret && ret != -EEXIST) {
+ VLOG_ERR("rte_mtr_destroy fail: err_type: %d err_msg: %s, portid: %d\n",
+ mtr_error.type, mtr_error.message, dmo->port_id);
+ }
+ VLOG_DBG("yunxiang_DBG:in dpdk_meter_destroy2, port_id is %d,mtr_id is %d", dmo->port_id, dmo->mc.mtr_id);
free(dmo);
}
}
@@ -1743,8 +1763,6 @@ parse_clone_actions(struct netdev *netdev,
NL_ATTR_FOR_EACH_UNSAFE (ca, cleft, clone_actions, clone_actions_len) {
int clone_type = nl_attr_type(ca);
- VLOG_DBG("TIMO DBG: in parse_clone_action %0d:%d",i++,clone_type);
-
if (clone_type == OVS_ACTION_ATTR_TUNNEL_PUSH) {
const struct ovs_action_push_tnl *tnl_push = nl_attr_get(ca);
@@ -1790,10 +1808,81 @@ parse_clone_actions(struct netdev *netdev,
return 0;
}
+#define DPDK_METER_UPATE_UP 65536
+
+static void dpdk_meter_update(void *priv_data, void *config)
+{
+ struct dpdk_meter_offload *dmo = priv_data;
+ struct rte_mtr_meter_profile mp;
+ struct rte_mtr_error mtr_error;
+ uint32_t mp_id, new_mp_id;
+ uint32_t *rate_and_burst;
+ uint32_t max_rate;
+ uint32_t burst_size;
+ uint32_t ret;
+
+ if (!priv_data || !config) {
+ return;
+ }
+
+ rate_and_burst = ofputil_meter_config_rate_burst(config);
+ max_rate = *rate_and_burst;
+ burst_size = *(rate_and_burst + 1);
+ VLOG_DBG("yunxiang_DBG:in dpdk_meter_update, max_rate is %d,burst is %d,dmo->nax_rate is %d", max_rate, burst_size, dmo->max_rate);
+
+ if (dmo->max_rate == max_rate) {
+ return;
+ }
+
+ memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
+ mp.alg = RTE_MTR_TRTCM_RFC2698;
+ mp.trtcm_rfc2698.cir = max_rate *1000 /8; /* rate_max Kbps*/
+ mp.trtcm_rfc2698.cbs = burst_size /8; /* busrt_size bit*/
+
+ if (dmo->mp_id < DPDK_METER_UPATE_UP) {
+ new_mp_id = dmo->mp_id + DPDK_METER_UPATE_UP;
+ } else {
+ new_mp_id = dmo->mp_id - DPDK_METER_UPATE_UP;
+ }
+
+ ret = rte_mtr_meter_profile_add(dmo->port_id, new_mp_id,
+ &mp, &mtr_error);
+ VLOG_DBG("yunxiang_DBG: in dpdk_meter_update_profile_add, port_id is %d,device name is %s, new_mp_id is %d, max_rate is %d, burst_size is %d", dmo->port_id, rte_eth_devices[dmo->port_id].data->name, new_mp_id,max_rate, burst_size);
+ if (ret) {
+ VLOG_ERR("rte_mtr_meter_profile_add fail: err_type: %d err_msg: %s\n",
+ mtr_error.type, mtr_error.message);
+ return;
+ }
+
+ ret = rte_mtr_meter_profile_update(dmo->port_id, dmo->mc.mtr_id,
+ new_mp_id, &mtr_error);
+ VLOG_DBG("yunxiang_DBG: in dpdk_meter_update_profile_update, max_rate is %d, burst_size is %d, mid is %d, new_mp_id is %d", max_rate, burst_size, dmo->mc.mtr_id, new_mp_id);
+ if (ret) {
+ VLOG_ERR("rte_mtr_meter_profile_update fail: err_type: %d err_msg: %s\n",
+ mtr_error.type, mtr_error.message);
+ mp_id = new_mp_id;
+ goto out;
+ }
+
+ mp_id = dmo->mp_id;
+ dmo->mp_id = new_mp_id;
+out:
+ ret = rte_mtr_meter_profile_delete(dmo->port_id, mp_id, &mtr_error);
+ if (ret) {
+ VLOG_ERR("rte_mtr_meter_profile_update fail: err_type: %d err_msg: %s\n",
+ mtr_error.type, mtr_error.message);
+ }
+}
+
+static struct netdev_offload_meter_api dpdk_meter_offload_api = {
+ .meter_destroy = dpdk_meter_destroy,
+ .meter_update = dpdk_meter_update,
+};
+
static struct rte_flow_action_meter*
dpdk_meter_create(struct dpif *dpif, struct netdev *netdev, uint32_t mid)
{
- uint32_t port_id = netdev_dpdk_get_portid(netdev);
+ uint32_t port_id;
struct netdev_offload_meter *nom;
struct dpdk_meter_offload *dmo;
struct ofputil_meter_config config;
@@ -1801,9 +1890,10 @@ dpdk_meter_create(struct dpif *dpif, struct netdev *netdev, uint32_t mid)
struct rte_mtr_meter_profile mp;
struct rte_mtr_params params;
struct rte_mtr_error mtr_error;
+ uint32_t *rate_and_burst;
uint32_t max_rate;
+ uint32_t burst_size;
int ret;
- static struct netdev_offload_meter_api dpdk_meter_offload_api;
meter_id.uint32 = mid;
@@ -1811,6 +1901,34 @@ dpdk_meter_create(struct dpif *dpif, struct netdev *netdev, uint32_t mid)
return NULL;
}
+ /* check if the device port is a useful rep port. If it is a vport, we
+ * we will get any rep port from all netdev */
+ if (netdev_vport_is_vport_class(netdev->netdev_class)) {
+ struct netdev_flow_dump **netdev_dumps;
+ int num_ports = 0;
+ int i;
+
+ netdev_dumps = netdev_ports_flow_dump_create(netdev->dpif_type,
+ &num_ports);
+ for (i = 0; i < num_ports; i++) {
+ if (!netdev_dpdk_is_vfrep_port(netdev_dumps[i]->netdev)) {
+ continue;
+ }
+ port_id = netdev_dpdk_get_portid(netdev_dumps[i]->netdev);
+ break;
+ }
+ for (i = 0; i < num_ports; i++) {
+ int err = netdev_flow_dump_destroy(netdev_dumps[i]);
+
+ if (err != 0 && err != EOPNOTSUPP) {
+ VLOG_ERR("failed dumping netdev: %s", ovs_strerror(err));
+ }
+ }
+
+ } else {
+ port_id = netdev_dpdk_get_portid(netdev);
+ }
+
nom = xmalloc(sizeof *nom);
dmo = xmalloc(sizeof *dmo);
@@ -1818,39 +1936,39 @@ dpdk_meter_create(struct dpif *dpif, struct netdev *netdev, uint32_t mid)
nom->priv_data = dmo;
memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
- max_rate = ofputil_meter_config_max_rate(&config);
+ rate_and_burst = ofputil_meter_config_rate_burst(&config);
+ max_rate = *rate_and_burst;
+ burst_size = *(rate_and_burst + 1);
dmo->mc.mtr_id = mid;
dmo->port_id = port_id;
dmo->max_rate = max_rate;
dmo->mp_id = mid;
- mp.alg = RTE_MTR_SRTCM_RFC2697;
- mp.srtcm_rfc2697.cir = max_rate *1024 /8; /* rate_max Kbps*/
- mp.srtcm_rfc2697.cbs = max_rate *1024 /8;
- mp.srtcm_rfc2697.ebs = 0;
-
+ mp.alg = RTE_MTR_TRTCM_RFC2698;
+ mp.trtcm_rfc2698.cir = max_rate *1000 /8; /* rate_max Kbps*/
+ mp.trtcm_rfc2698.cbs = burst_size /8; /* busrt_size bit*/
+
+ VLOG_DBG("yunxiang_DBG: in dpdk_meter_create, port_id1 is %d,device name is %s", dmo->port_id, rte_eth_devices[port_id].data->name);
ret = rte_mtr_meter_profile_add(dmo->port_id, dmo->mc.mtr_id,
&mp, &mtr_error);
+ VLOG_DBG("yunxiang_DBG: in dpdk_meter_create, max_rate is %d, burst_size is %d, mid is %d", max_rate, burst_size, dmo->mc.mtr_id);
if (ret && ret != -EEXIST) {
VLOG_ERR("rte_mtr_meter_profile_add fail: err_type: %d err_msg: %s, portid: %d\n",
mtr_error.type, mtr_error.message, netdev_dpdk_get_portid(netdev));
goto profile_err;
}
- enum rte_color dscp_table[2];
- dscp_table[0] = RTE_COLOR_YELLOW;
- dscp_table[1] = RTE_COLOR_RED;
params.meter_profile_id = dmo->mc.mtr_id;
- params.dscp_table = dscp_table;
params.meter_enable = 1;
params.use_prev_mtr_color = 0;
+ params.stats_mask = 0;
params.action[RTE_COLOR_GREEN] = MTR_POLICER_ACTION_COLOR_GREEN;
params.action[RTE_COLOR_YELLOW] = MTR_POLICER_ACTION_DROP;
params.action[RTE_COLOR_RED] = MTR_POLICER_ACTION_DROP;
- ret = rte_mtr_create(dmo->port_id, dmo->mc.mtr_id, ¶ms, 0, &mtr_error);
+ ret = rte_mtr_create(dmo->port_id, dmo->mc.mtr_id, ¶ms, 1, &mtr_error);
if (ret && ret != -EEXIST) {
VLOG_ERR("rte_mtr_create fail: err_type: %d err_msg: %s, portid: %d\n",
mtr_error.type, mtr_error.message, netdev_dpdk_get_portid(netdev));
@@ -1875,7 +1993,7 @@ profile_err:
static struct rte_flow_action_meter *
netdev_offload_dpdk_meter_conf(struct dpif *dpif, struct netdev *netdev, uint32_t mid)
{
- uint32_t port_id = netdev_dpdk_get_portid(netdev);
+ /*uint32_t port_id = netdev_dpdk_get_portid(netdev);*/
struct netdev_offload_meter *nom = NULL;
struct dpdk_meter_offload *dmo;
ofproto_meter_id meter_id;
@@ -1891,16 +2009,11 @@ netdev_offload_dpdk_meter_conf(struct dpif *dpif, struct netdev *netdev, uint32_
if (!nom) {
return dpdk_meter_create(dpif, netdev, mid);
+ } else {
+ dmo = (struct dpdk_meter_offload *)(nom->priv_data);
+ return &(dmo->mc);
}
- dmo = (struct dpdk_meter_offload *)nom->priv_data;
- if (port_id != dmo->port_id) {
- VLOG_INFO("dpdk meter %d is used on %d, can't be used for : %d",
- mid, dmo->port_id, port_id);
- return NULL;
- }
-
- return &dmo->mc;
}
static int
@@ -1980,12 +2093,17 @@ parse_flow_actions(struct dpif *dpif,
/* for ct && ct clear no need to translate*/
} else if (nl_attr_type(nla) == OVS_ACTION_ATTR_METER) {
struct rte_flow_action_meter *mc;
- mc = netdev_offload_dpdk_meter_conf(dpif,
+ struct rte_flow_action_meter *mc_ori;
+ mc_ori = netdev_offload_dpdk_meter_conf(dpif,
netdev,
nl_attr_get_u32(nla));
- if (mc) {
+ if (mc_ori) {
+ mc = xzalloc(sizeof *mc);
+ mc->mtr_id = nl_attr_get_u32(nla);
add_flow_action(actions, RTE_FLOW_ACTION_TYPE_METER, mc);
- }
+ } else {
+ return -1;
+ }
}
else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT_CLEAR ||
@@ -2053,7 +2171,6 @@ netdev_offload_dpdk_actions(struct dpif *dpif,
if (!netdev_dpdk_is_uplink_port(netdev_dumps[i]->netdev)) {
continue;
}
- VLOG_DBG("TIMO DBG: in netdev_offload_dpdk_flow_create, netdev dpdk");
flow = netdev_offload_dpdk_flow_create(netdev_dumps[i]->netdev,
&flow_attr, patterns->items,
actions.actions, &error);
@@ -2063,7 +2180,7 @@ netdev_offload_dpdk_actions(struct dpif *dpif,
int err = netdev_flow_dump_destroy(netdev_dumps[i]);
if (err != 0 && err != EOPNOTSUPP) {
- VLOG_ERR("failed dumping netdev: %s", ovs_strerror(err));
+ VLOG_ERR("dpdk_action:failed dumping netdev: %s", ovs_strerror(err));
}
}
@@ -2076,71 +2193,6 @@ out:
return flow;
}
-#define DPDK_METER_UPATE_UP 65536
-
-static void dpdk_meter_update(void *priv_data, void *config)
-{
- struct dpdk_meter_offload *dmo = priv_data;
- struct rte_mtr_meter_profile mp;
- struct rte_mtr_error mtr_error;
- uint32_t mp_id, new_mp_id;
- uint32_t max_rate;
- uint32_t ret;
-
- if (!priv_data || !config) {
- return;
- }
-
- max_rate = ofputil_meter_config_max_rate(config);
- if (dmo->max_rate == max_rate) {
- return;
- }
-
- memset(&mp, 0, sizeof(struct rte_mtr_meter_profile));
- mp.alg = RTE_MTR_SRTCM_RFC2697;
- mp.srtcm_rfc2697.cir = max_rate *1024 /8;
- mp.srtcm_rfc2697.cbs = max_rate *1024 /8;
- mp.srtcm_rfc2697.ebs = 0;
-
- if (dmo->mp_id < DPDK_METER_UPATE_UP) {
- new_mp_id = dmo->mp_id + DPDK_METER_UPATE_UP;
- } else {
- new_mp_id = dmo->mp_id - DPDK_METER_UPATE_UP;
- }
-
- ret = rte_mtr_meter_profile_add(dmo->port_id, new_mp_id,
- &mp, &mtr_error);
- if (ret) {
- VLOG_ERR("rte_mtr_meter_profile_add fail: err_type: %d err_msg: %s\n",
- mtr_error.type, mtr_error.message);
- return;
- }
-
- ret = rte_mtr_meter_profile_update(dmo->port_id, dmo->mc.mtr_id,
- new_mp_id, &mtr_error);
- if (ret) {
- VLOG_ERR("rte_mtr_meter_profile_update fail: err_type: %d err_msg: %s\n",
- mtr_error.type, mtr_error.message);
- mp_id = new_mp_id;
- goto out;
- }
-
- mp_id = dmo->mp_id;
- dmo->mp_id = new_mp_id;
-out:
- ret = rte_mtr_meter_profile_delete(dmo->port_id, mp_id, &mtr_error);
- if (ret) {
- VLOG_ERR("rte_mtr_meter_profile_update fail: err_type: %d err_msg: %s\n",
- mtr_error.type, mtr_error.message);
- }
-}
-
-static struct netdev_offload_meter_api dpdk_meter_offload_api = {
- .meter_destroy = dpdk_meter_destroy,
- .meter_update = dpdk_meter_update,
-};
-
-
static int
netdev_offload_dpdk_add_flow(struct dpif *dpif, struct netdev *netdev,
@@ -2158,12 +2210,10 @@ netdev_offload_dpdk_add_flow(struct dpif *dpif, struct netdev *netdev,
ret = parse_flow_match(&patterns, match, netdev, info);
if (ret) {
goto out;
- VLOG_DBG("yunxiang_debug_netdev_offload_dpdk_add_flow: ret %p \n",ret);
}
flow = netdev_offload_dpdk_actions(dpif, netdev, &patterns, nl_actions,
actions_len, info);
- VLOG_DBG("yunxiang_debug_netdev_offload_dpdk_add_flow: flow %p \n",flow);
if (!flow) {
/* If we failed to offload the rule actions fallback to MARK+RSS
* actions.
@@ -2197,7 +2247,6 @@ netdev_offload_dpdk_validate_flow(const struct match *match)
/* Create a wc-zeroed version of flow. */
match_init(&match_zero_wc, &match->flow, &match->wc);
-
/* support tunnel now so mark this checker
if (!is_all_zeros(&match_zero_wc.flow.tunnel,
sizeof match_zero_wc.flow.tunnel)) {
@@ -2306,12 +2355,35 @@ netdev_offload_dpdk_flow_put(struct dpif *dpif, struct netdev *netdev,
* Here destroy the old rte flow first before adding a new one.
*/
rte_flow_data = ufid_to_rte_flow_data_find(ufid);
- VLOG_DBG("yunxiang_debug_netdev_offload_dpdk_flow_put,rte_flow_data=%p",rte_flow_data);
if (rte_flow_data && rte_flow_data->rte_flow) {
- ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
- rte_flow_data->rte_flow);
+ if (netdev_vport_is_vport_class(netdev->netdev_class)) {
+ struct netdev_flow_dump **netdev_dumps;
+ int num_ports = 0;
+ int i;
+
+ netdev_dumps = netdev_ports_flow_dump_create(netdev->dpif_type,
+ &num_ports);
+ for (i = 0; i < num_ports; i++) {
+ if (!netdev_dpdk_is_uplink_port(netdev_dumps[i]->netdev)) {
+ continue;
+ }
+ ret = netdev_offload_dpdk_destroy_flow(netdev_dumps[i]->netdev, ufid,
+ rte_flow_data->rte_flow);
+ break;
+ }
+ for (i = 0; i < num_ports; i++) {
+ int err = netdev_flow_dump_destroy(netdev_dumps[i]);
+
+ if (err != 0 && err != EOPNOTSUPP) {
+ VLOG_ERR("flow_del:failed dumping netdev: %s", ovs_strerror(err));
+ }
+ }
+
+ } else {
+ ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
+ rte_flow_data->rte_flow);
+ }
if (ret < 0) {
- VLOG_DBG("yunxiang_debug_netdev_offload_dpdk_flow_put,ret=%p",ret);
return ret;
}
}
@@ -2333,17 +2405,44 @@ netdev_offload_dpdk_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
struct dpif_flow_stats *stats)
{
struct ufid_to_rte_flow_data *rte_flow_data;
+ int ret = -1;
rte_flow_data = ufid_to_rte_flow_data_find(ufid);
if (!rte_flow_data || !rte_flow_data->rte_flow) {
- return -1;
+ return ret;
}
if (stats) {
memset(stats, 0, sizeof *stats);
}
- return netdev_offload_dpdk_destroy_flow(netdev, ufid,
- rte_flow_data->rte_flow);
+ if (netdev_vport_is_vport_class(netdev->netdev_class)) {
+ struct netdev_flow_dump **netdev_dumps;
+ int num_ports = 0;
+ int i;
+
+ netdev_dumps = netdev_ports_flow_dump_create(netdev->dpif_type,
+ &num_ports);
+ for (i = 0; i < num_ports; i++) {
+ if (!netdev_dpdk_is_uplink_port(netdev_dumps[i]->netdev)) {
+ continue;
+ }
+ ret = netdev_offload_dpdk_destroy_flow(netdev_dumps[i]->netdev, ufid,
+ rte_flow_data->rte_flow);
+ break;
+ }
+ for (i = 0; i < num_ports; i++) {
+ int err = netdev_flow_dump_destroy(netdev_dumps[i]);
+
+ if (err != 0 && err != EOPNOTSUPP) {
+ VLOG_ERR("flow_del:failed dumping netdev: %s", ovs_strerror(err));
+ }
+ }
+
+ } else {
+ ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
+ rte_flow_data->rte_flow);
+ }
+ return ret;
}
static int
@@ -808,16 +808,19 @@ ofputil_format_meter_mod(struct ds *s, const struct ofputil_meter_mod *mm)
ofputil_format_meter_config(s, &mm->meter);
}
-uint32_t
-ofputil_meter_config_max_rate(struct ofputil_meter_config *conf)
+uint32_t *
+ofputil_meter_config_rate_burst(struct ofputil_meter_config *conf)
{
- uint32_t i, max_rate = 0;
+ uint32_t i, max_rate = 0, burst_size = 0;
+ uint32_t rate_and_burst[2];
for (i = 0; i < conf->n_bands; i++) {
if (max_rate < conf->bands[i].rate) {
max_rate = conf->bands[i].rate;
+ burst_size = conf->bands[i].burst_size;
}
}
-
- return max_rate;
+ rate_and_burst[0] = max_rate;
+ rate_and_burst[1] = burst_size;
+
+ return rate_and_burst;
}
-
From: Taoyunxiang <taoyunxiang@cmss.chinamobile.com> Code Source From: Self Code Description: Fix crash and port get bug when offload meter and vxlan Jira: #[Optional] 市场项目编号(名称):[Optional] --- include/openvswitch/ofp-meter.h | 2 +- lib/dpif-netdev.c | 10 -- lib/netdev-offload-dpdk.c | 319 ++++++++++++++++++++++++++-------------- lib/ofp-meter.c | 15 +- 4 files changed, 219 insertions(+), 127 deletions(-)