2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-30 22:05:19 +00:00

dpif-netdev: create batch object

DPDK datapath operate on batch of packets. To pass the batch of
packets around we use packets array and count.  Next patch needs
to associate meta-data with each batch of packets. So Introducing
a batch structure to make handling the metadata easier.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
This commit is contained in:
Pravin B Shelar
2016-05-17 17:32:33 -07:00
parent f7ce48110d
commit 1895cc8dbb
8 changed files with 154 additions and 122 deletions

View File

@@ -563,6 +563,49 @@ dp_packet_rss_invalidate(struct dp_packet *p)
#endif
}
enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */
struct dp_packet_batch {
int count;
struct dp_packet *packets[NETDEV_MAX_BURST];
};
static inline void dp_packet_batch_init(struct dp_packet_batch *b)
{
b->count = 0;
}
static inline void
dp_packet_batch_clone(struct dp_packet_batch *dst,
struct dp_packet_batch *src)
{
int i;
for (i = 0; i < src->count; i++) {
dst->packets[i] = dp_packet_clone(src->packets[i]);
}
dst->count = src->count;
}
static inline void
packet_batch_init_packet(struct dp_packet_batch *b, struct dp_packet *p)
{
b->count = 1;
b->packets[0] = p;
}
static inline void
dp_packet_delete_batch(struct dp_packet_batch *batch, bool may_steal)
{
if (may_steal) {
int i;
for (i = 0; i < batch->count; i++) {
dp_packet_delete(batch->packets[i]);
}
}
}
#ifdef __cplusplus
}
#endif

View File

@@ -473,14 +473,14 @@ static void do_del_port(struct dp_netdev *dp, struct dp_netdev_port *)
static int dpif_netdev_open(const struct dpif_class *, const char *name,
bool create, struct dpif **);
static void dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **, int c,
struct dp_packet_batch *,
bool may_steal,
const struct nlattr *actions,
size_t actions_len);
static void dp_netdev_input(struct dp_netdev_pmd_thread *,
struct dp_packet **, int cnt, odp_port_t port_no);
struct dp_packet_batch *, odp_port_t port_no);
static void dp_netdev_recirculate(struct dp_netdev_pmd_thread *,
struct dp_packet **, int cnt);
struct dp_packet_batch *);
static void dp_netdev_disable_upcall(struct dp_netdev *);
static void dp_netdev_pmd_reload_done(struct dp_netdev_pmd_thread *pmd);
@@ -2342,7 +2342,7 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_pmd_thread *pmd;
struct dp_packet *pp;
struct dp_packet_batch pp;
if (dp_packet_size(execute->packet) < ETH_HEADER_LEN ||
dp_packet_size(execute->packet) > UINT16_MAX) {
@@ -2364,8 +2364,8 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
ovs_mutex_lock(&dp->port_mutex);
}
pp = execute->packet;
dp_netdev_execute_actions(pmd, &pp, 1, false, execute->actions,
packet_batch_init_packet(&pp, execute->packet);
dp_netdev_execute_actions(pmd, &pp, false, execute->actions,
execute->actions_len);
if (pmd->core_id == NON_PMD_CORE_ID) {
dp_netdev_pmd_unref(pmd);
@@ -2559,17 +2559,18 @@ dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd,
struct dp_netdev_port *port,
struct netdev_rxq *rxq)
{
struct dp_packet *packets[NETDEV_MAX_BURST];
int error, cnt;
struct dp_packet_batch batch;
int error;
dp_packet_batch_init(&batch);
cycles_count_start(pmd);
error = netdev_rxq_recv(rxq, packets, &cnt);
error = netdev_rxq_recv(rxq, &batch);
cycles_count_end(pmd, PMD_CYCLES_POLLING);
if (!error) {
*recirc_depth_get() = 0;
cycles_count_start(pmd);
dp_netdev_input(pmd, packets, cnt, port->port_no);
dp_netdev_input(pmd, &batch, port->port_no);
cycles_count_end(pmd, PMD_CYCLES_PROCESSING);
} else if (error != EAGAIN && error != EOPNOTSUPP) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -3330,13 +3331,11 @@ dpif_netdev_packet_get_rss_hash(struct dp_packet *packet,
}
struct packet_batch_per_flow {
unsigned int packet_count;
unsigned int byte_count;
uint16_t tcp_flags;
struct dp_netdev_flow *flow;
struct dp_packet *packets[NETDEV_MAX_BURST];
struct dp_packet_batch array;
};
static inline void
@@ -3344,9 +3343,9 @@ packet_batch_per_flow_update(struct packet_batch_per_flow *batch,
struct dp_packet *packet,
const struct miniflow *mf)
{
batch->tcp_flags |= miniflow_get_tcp_flags(mf);
batch->packets[batch->packet_count++] = packet;
batch->byte_count += dp_packet_size(packet);
batch->tcp_flags |= miniflow_get_tcp_flags(mf);
batch->array.packets[batch->array.count++] = packet;
}
static inline void
@@ -3356,7 +3355,7 @@ packet_batch_per_flow_init(struct packet_batch_per_flow *batch,
flow->batch = batch;
batch->flow = flow;
batch->packet_count = 0;
dp_packet_batch_init(&batch->array);
batch->byte_count = 0;
batch->tcp_flags = 0;
}
@@ -3369,12 +3368,12 @@ packet_batch_per_flow_execute(struct packet_batch_per_flow *batch,
struct dp_netdev_actions *actions;
struct dp_netdev_flow *flow = batch->flow;
dp_netdev_flow_used(flow, batch->packet_count, batch->byte_count,
dp_netdev_flow_used(flow, batch->array.count, batch->byte_count,
batch->tcp_flags, now);
actions = dp_netdev_flow_get_actions(flow);
dp_netdev_execute_actions(pmd, batch->packets, batch->packet_count, true,
dp_netdev_execute_actions(pmd, &batch->array, true,
actions->actions, actions->size);
}
@@ -3405,14 +3404,16 @@ dp_netdev_queue_batches(struct dp_packet *pkt,
* initialized by this function using 'port_no'.
*/
static inline size_t
emc_processing(struct dp_netdev_pmd_thread *pmd, struct dp_packet **packets,
size_t cnt, struct netdev_flow_key *keys,
emc_processing(struct dp_netdev_pmd_thread *pmd, struct dp_packet_batch *packets_,
struct netdev_flow_key *keys,
struct packet_batch_per_flow batches[], size_t *n_batches,
bool md_is_valid, odp_port_t port_no)
{
struct emc_cache *flow_cache = &pmd->flow_cache;
struct netdev_flow_key *key = &keys[0];
size_t i, n_missed = 0, n_dropped = 0;
struct dp_packet **packets = packets_->packets;
int cnt = packets_->count;
for (i = 0; i < cnt; i++) {
struct dp_netdev_flow *flow;
@@ -3459,19 +3460,22 @@ emc_processing(struct dp_netdev_pmd_thread *pmd, struct dp_packet **packets,
static inline void
fast_path_processing(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **packets, size_t cnt,
struct dp_packet_batch *packets_,
struct netdev_flow_key *keys,
struct packet_batch_per_flow batches[], size_t *n_batches)
{
int cnt = packets_->count;
#if !defined(__CHECKER__) && !defined(_WIN32)
const size_t PKT_ARRAY_SIZE = cnt;
#else
/* Sparse or MSVC doesn't like variable length array. */
enum { PKT_ARRAY_SIZE = NETDEV_MAX_BURST };
#endif
struct dp_packet **packets = packets_->packets;
struct dpcls_rule *rules[PKT_ARRAY_SIZE];
struct dp_netdev *dp = pmd->dp;
struct emc_cache *flow_cache = &pmd->flow_cache;
struct dp_packet_batch b;
int miss_cnt = 0, lost_cnt = 0;
bool any_miss;
size_t i;
@@ -3539,7 +3543,8 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
/* We can't allow the packet batching in the next loop to execute
* the actions. Otherwise, if there are any slow path actions,
* we'll send the packet up twice. */
dp_netdev_execute_actions(pmd, &packets[i], 1, true,
packet_batch_init_packet(&b, packets[i]);
dp_netdev_execute_actions(pmd, &b, true,
actions.data, actions.size);
add_actions = put_actions.size ? &put_actions : &actions;
@@ -3604,9 +3609,10 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
* valid, 'md_is_valid' must be true and 'port_no' will be ignored. */
static void
dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **packets, int cnt,
struct dp_packet_batch *packets,
bool md_is_valid, odp_port_t port_no)
{
int cnt = packets->count;
#if !defined(__CHECKER__) && !defined(_WIN32)
const size_t PKT_ARRAY_SIZE = cnt;
#else
@@ -3619,10 +3625,11 @@ dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
size_t newcnt, n_batches, i;
n_batches = 0;
newcnt = emc_processing(pmd, packets, cnt, keys, batches, &n_batches,
newcnt = emc_processing(pmd, packets, keys, batches, &n_batches,
md_is_valid, port_no);
if (OVS_UNLIKELY(newcnt)) {
fast_path_processing(pmd, packets, newcnt, keys, batches, &n_batches);
packets->count = newcnt;
fast_path_processing(pmd, packets, keys, batches, &n_batches);
}
for (i = 0; i < n_batches; i++) {
@@ -3636,17 +3643,17 @@ dp_netdev_input__(struct dp_netdev_pmd_thread *pmd,
static void
dp_netdev_input(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **packets, int cnt,
struct dp_packet_batch *packets,
odp_port_t port_no)
{
dp_netdev_input__(pmd, packets, cnt, false, port_no);
dp_netdev_input__(pmd, packets, false, port_no);
}
static void
dp_netdev_recirculate(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **packets, int cnt)
struct dp_packet_batch *packets)
{
dp_netdev_input__(pmd, packets, cnt, true, 0);
dp_netdev_input__(pmd, packets, true, 0);
}
struct dp_netdev_execute_aux {
@@ -3671,22 +3678,10 @@ dpif_netdev_register_upcall_cb(struct dpif *dpif, upcall_callback *cb,
dp->upcall_cb = cb;
}
static void
dp_netdev_drop_packets(struct dp_packet **packets, int cnt, bool may_steal)
{
if (may_steal) {
int i;
for (i = 0; i < cnt; i++) {
dp_packet_delete(packets[i]);
}
}
}
static int
push_tnl_action(const struct dp_netdev *dp,
const struct nlattr *attr,
struct dp_packet **packets, int cnt)
const struct nlattr *attr,
struct dp_packet_batch *batch)
{
struct dp_netdev_port *tun_port;
const struct ovs_action_push_tnl *data;
@@ -3697,24 +3692,13 @@ push_tnl_action(const struct dp_netdev *dp,
if (!tun_port) {
return -EINVAL;
}
netdev_push_header(tun_port->netdev, packets, cnt, data);
netdev_push_header(tun_port->netdev, batch, data);
return 0;
}
static void
dp_netdev_clone_pkt_batch(struct dp_packet **dst_pkts,
struct dp_packet **src_pkts, int cnt)
{
int i;
for (i = 0; i < cnt; i++) {
dst_pkts[i] = dp_packet_clone(src_pkts[i]);
}
}
static void
dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
const struct nlattr *a, bool may_steal)
OVS_NO_THREAD_SAFETY_ANALYSIS
{
@@ -3733,28 +3717,28 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
atomic_read_relaxed(&pmd->tx_qid, &tx_qid);
netdev_send(p->netdev, tx_qid, packets, cnt, may_steal);
netdev_send(p->netdev, tx_qid, packets_, may_steal);
return;
}
break;
case OVS_ACTION_ATTR_TUNNEL_PUSH:
if (*depth < MAX_RECIRC_DEPTH) {
struct dp_packet *tnl_pkt[NETDEV_MAX_BURST];
struct dp_packet_batch tnl_pkt;
int err;
if (!may_steal) {
dp_netdev_clone_pkt_batch(tnl_pkt, packets, cnt);
packets = tnl_pkt;
dp_packet_batch_clone(&tnl_pkt, packets_);
packets_ = &tnl_pkt;
}
err = push_tnl_action(dp, a, packets, cnt);
err = push_tnl_action(dp, a, packets_);
if (!err) {
(*depth)++;
dp_netdev_recirculate(pmd, packets, cnt);
dp_netdev_recirculate(pmd, packets_);
(*depth)--;
} else {
dp_netdev_drop_packets(tnl_pkt, cnt, !may_steal);
dp_packet_delete_batch(&tnl_pkt, !may_steal);
}
return;
}
@@ -3766,30 +3750,30 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
p = dp_netdev_lookup_port(dp, portno);
if (p) {
struct dp_packet *tnl_pkt[NETDEV_MAX_BURST];
struct dp_packet_batch tnl_pkt;
int err;
if (!may_steal) {
dp_netdev_clone_pkt_batch(tnl_pkt, packets, cnt);
packets = tnl_pkt;
dp_packet_batch_clone(&tnl_pkt, packets_);
packets_ = &tnl_pkt;
}
err = netdev_pop_header(p->netdev, packets, &cnt);
if (!cnt) {
err = netdev_pop_header(p->netdev, packets_);
if (!packets_->count) {
return;
}
if (!err) {
int i;
for (i = 0; i < cnt; i++) {
packets[i]->md.in_port.odp_port = portno;
for (i = 0; i < packets_->count; i++) {
packets_->packets[i]->md.in_port.odp_port = portno;
}
(*depth)++;
dp_netdev_recirculate(pmd, packets, cnt);
dp_netdev_recirculate(pmd, packets_);
(*depth)--;
} else {
dp_netdev_drop_packets(tnl_pkt, cnt, !may_steal);
dp_packet_delete_batch(&tnl_pkt, !may_steal);
}
return;
}
@@ -3798,6 +3782,7 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
case OVS_ACTION_ATTR_USERSPACE:
if (!fat_rwlock_tryrdlock(&dp->upcall_rwlock)) {
struct dp_packet **packets = packets_->packets;
const struct nlattr *userdata;
struct ofpbuf actions;
struct flow flow;
@@ -3807,8 +3792,9 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA);
ofpbuf_init(&actions, 0);
for (i = 0; i < cnt; i++) {
for (i = 0; i < packets_->count; i++) {
int error;
struct dp_packet_batch b;
ofpbuf_clear(&actions);
@@ -3818,7 +3804,8 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
DPIF_UC_ACTION, userdata,&actions,
NULL);
if (!error || error == ENOSPC) {
dp_netdev_execute_actions(pmd, &packets[i], 1, may_steal,
packet_batch_init_packet(&b, packets[i]);
dp_netdev_execute_actions(pmd, &b, may_steal,
actions.data, actions.size);
} else if (may_steal) {
dp_packet_delete(packets[i]);
@@ -3833,20 +3820,20 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
case OVS_ACTION_ATTR_RECIRC:
if (*depth < MAX_RECIRC_DEPTH) {
struct dp_packet *recirc_pkts[NETDEV_MAX_BURST];
struct dp_packet_batch recirc_pkts;
int i;
if (!may_steal) {
dp_netdev_clone_pkt_batch(recirc_pkts, packets, cnt);
packets = recirc_pkts;
dp_packet_batch_clone(&recirc_pkts, packets_);
packets_ = &recirc_pkts;
}
for (i = 0; i < cnt; i++) {
packets[i]->md.recirc_id = nl_attr_get_u32(a);
for (i = 0; i < packets_->count; i++) {
packets_->packets[i]->md.recirc_id = nl_attr_get_u32(a);
}
(*depth)++;
dp_netdev_recirculate(pmd, packets, cnt);
dp_netdev_recirculate(pmd, packets_);
(*depth)--;
return;
@@ -3875,18 +3862,18 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt,
OVS_NOT_REACHED();
}
dp_netdev_drop_packets(packets, cnt, may_steal);
dp_packet_delete_batch(packets_, may_steal);
}
static void
dp_netdev_execute_actions(struct dp_netdev_pmd_thread *pmd,
struct dp_packet **packets, int cnt,
struct dp_packet_batch *packets,
bool may_steal,
const struct nlattr *actions, size_t actions_len)
{
struct dp_netdev_execute_aux aux = { pmd };
odp_execute_actions(&aux, packets, cnt, may_steal, actions,
odp_execute_actions(&aux, packets, may_steal, actions,
actions_len, dp_execute_cb);
}

View File

@@ -1087,14 +1087,14 @@ struct dpif_execute_helper_aux {
/* This is called for actions that need the context of the datapath to be
* meaningful. */
static void
dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt,
dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
const struct nlattr *action, bool may_steal OVS_UNUSED)
{
struct dpif_execute_helper_aux *aux = aux_;
int type = nl_attr_type(action);
struct dp_packet *packet = *packets;
struct dp_packet *packet = packets_->packets[0];
ovs_assert(cnt == 1);
ovs_assert(packets_->count == 1);
switch ((enum ovs_action_attr)type) {
case OVS_ACTION_ATTR_CT:
@@ -1161,12 +1161,12 @@ static int
dpif_execute_with_help(struct dpif *dpif, struct dpif_execute *execute)
{
struct dpif_execute_helper_aux aux = {dpif, 0};
struct dp_packet *pp;
struct dp_packet_batch pb;
COVERAGE_INC(dpif_execute_with_help);
pp = execute->packet;
odp_execute_actions(&aux, &pp, 1, false, execute->actions,
packet_batch_init_packet(&pb, execute->packet);
odp_execute_actions(&aux, &pb, false, execute->actions,
execute->actions_len, dpif_execute_helper_cb);
return aux.error;
}

View File

@@ -624,15 +624,15 @@ netdev_rxq_close(struct netdev_rxq *rx)
* Returns EAGAIN immediately if no packet is ready to be received or another
* positive errno value if an error was encountered. */
int
netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet **pkts, int *cnt)
netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *batch)
{
int retval;
retval = rx->netdev->netdev_class->rxq_recv(rx, pkts, cnt);
retval = rx->netdev->netdev_class->rxq_recv(rx, batch->packets, &batch->count);
if (!retval) {
COVERAGE_INC(netdev_received);
} else {
*cnt = 0;
batch->count = 0;
}
return retval;
}
@@ -713,19 +713,16 @@ netdev_set_multiq(struct netdev *netdev, unsigned int n_txq,
* Some network devices may not implement support for this function. In such
* cases this function will always return EOPNOTSUPP. */
int
netdev_send(struct netdev *netdev, int qid, struct dp_packet **buffers,
int cnt, bool may_steal)
netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
bool may_steal)
{
if (!netdev->netdev_class->send) {
if (may_steal) {
for (int i = 0; i < cnt; i++) {
dp_packet_delete(buffers[i]);
}
}
dp_packet_delete_batch(batch, may_steal);
return EOPNOTSUPP;
}
int error = netdev->netdev_class->send(netdev, qid, buffers, cnt,
int error = netdev->netdev_class->send(netdev, qid,
batch->packets, batch->count,
may_steal);
if (!error) {
COVERAGE_INC(netdev_sent);
@@ -734,21 +731,22 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet **buffers,
}
int
netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers, int *pcnt)
netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *batch)
{
int i, cnt = *pcnt, n_cnt = 0;
int i, n_cnt = 0;
struct dp_packet **buffers = batch->packets;
if (!netdev->netdev_class->pop_header) {
return EOPNOTSUPP;
}
for (i = 0; i < cnt; i++) {
for (i = 0; i < batch->count; i++) {
buffers[i] = netdev->netdev_class->pop_header(buffers[i]);
if (buffers[i]) {
buffers[n_cnt++] = buffers[i];
}
}
*pcnt = n_cnt;
batch->count = n_cnt;
return 0;
}
@@ -764,7 +762,7 @@ netdev_build_header(const struct netdev *netdev, struct ovs_action_push_tnl *dat
int
netdev_push_header(const struct netdev *netdev,
struct dp_packet **buffers, int cnt,
struct dp_packet_batch *batch,
const struct ovs_action_push_tnl *data)
{
int i;
@@ -773,9 +771,9 @@ netdev_push_header(const struct netdev *netdev,
return -EINVAL;
}
for (i = 0; i < cnt; i++) {
netdev->netdev_class->push_header(buffers[i], data);
pkt_metadata_init(&buffers[i]->md, u32_to_odp(data->out_port));
for (i = 0; i < batch->count; i++) {
netdev->netdev_class->push_header(batch->packets[i], data);
pkt_metadata_init(&batch->packets[i]->md, u32_to_odp(data->out_port));
}
return 0;

View File

@@ -59,6 +59,7 @@ extern "C" {
* netdev and access each of those from a different thread.)
*/
struct dp_packet_batch;
struct dp_packet;
struct netdev_class;
struct netdev_rxq;
@@ -143,23 +144,21 @@ void netdev_rxq_close(struct netdev_rxq *);
const char *netdev_rxq_get_name(const struct netdev_rxq *);
int netdev_rxq_get_queue_id(const struct netdev_rxq *);
int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet **buffers,
int *cnt);
int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *);
void netdev_rxq_wait(struct netdev_rxq *);
int netdev_rxq_drain(struct netdev_rxq *);
/* Packet transmission. */
int netdev_send(struct netdev *, int qid, struct dp_packet **, int cnt,
int netdev_send(struct netdev *, int qid, struct dp_packet_batch *,
bool may_steal);
void netdev_send_wait(struct netdev *, int qid);
int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data,
const struct flow *tnl_flow);
int netdev_push_header(const struct netdev *netdev,
struct dp_packet **buffers, int cnt,
struct dp_packet_batch *,
const struct ovs_action_push_tnl *data);
int netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers,
int *pcnt);
int netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *);
/* Hardware address. */
int netdev_set_etheraddr(struct netdev *, const struct eth_addr mac);
@@ -276,7 +275,6 @@ typedef void netdev_dump_queue_stats_cb(unsigned int queue_id,
int netdev_dump_queue_stats(const struct netdev *,
netdev_dump_queue_stats_cb *, void *aux);
enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */
extern struct seq *tnl_conf_seq;
#ifndef _WIN32

View File

@@ -448,6 +448,7 @@ odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
{
const struct nlattr *subactions = NULL;
const struct nlattr *a;
struct dp_packet_batch pb;
size_t left;
NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
@@ -474,7 +475,8 @@ odp_execute_sample(void *dp, struct dp_packet *packet, bool steal,
}
}
odp_execute_actions(dp, &packet, 1, steal, nl_attr_get(subactions),
packet_batch_init_packet(&pb, packet);
odp_execute_actions(dp, &pb, steal, nl_attr_get(subactions),
nl_attr_get_size(subactions), dp_execute_action);
}
@@ -512,10 +514,12 @@ requires_datapath_assistance(const struct nlattr *a)
}
void
odp_execute_actions(void *dp, struct dp_packet **packets, int cnt, bool steal,
odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
const struct nlattr *actions, size_t actions_len,
odp_execute_cb dp_execute_action)
{
struct dp_packet **packets = batch->packets;
int cnt = batch->count;
const struct nlattr *a;
unsigned int left;
int i;
@@ -530,7 +534,7 @@ odp_execute_actions(void *dp, struct dp_packet **packets, int cnt, bool steal,
* not need it any more. */
bool may_steal = steal && last_action;
dp_execute_action(dp, packets, cnt, a, may_steal);
dp_execute_action(dp, batch, a, may_steal);
if (last_action) {
/* We do not need to free the packets. dp_execute_actions()

View File

@@ -26,15 +26,16 @@
struct nlattr;
struct dp_packet;
struct pkt_metadata;
struct dp_packet_batch;
typedef void (*odp_execute_cb)(void *dp, struct dp_packet **packets, int cnt,
typedef void (*odp_execute_cb)(void *dp, struct dp_packet_batch *batch,
const struct nlattr *action, bool may_steal);
/* Actions that need to be executed in the context of a datapath are handed
* to 'dp_execute_action', if non-NULL. Currently this is called only for
* actions OVS_ACTION_ATTR_OUTPUT and OVS_ACTION_ATTR_USERSPACE so
* 'dp_execute_action' needs to handle only these. */
void odp_execute_actions(void *dp, struct dp_packet **packets, int cnt,
void odp_execute_actions(void *dp, struct dp_packet_batch *batch,
bool steal,
const struct nlattr *actions, size_t actions_len,
odp_execute_cb dp_execute_action);

View File

@@ -3605,6 +3605,7 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
uint16_t controller_id,
const uint8_t *userdata, size_t userdata_len)
{
struct dp_packet_batch batch;
struct dp_packet *packet;
ctx->xout->slow |= SLOW_CONTROLLER;
@@ -3614,8 +3615,8 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
}
packet = dp_packet_clone(ctx->xin->packet);
odp_execute_actions(NULL, &packet, 1, false,
packet_batch_init_packet(&batch, packet);
odp_execute_actions(NULL, &batch, false,
ctx->odp_actions->data, ctx->odp_actions->size, NULL);
/* A packet sent by an action in a table-miss rule is considered an