From 1895cc8dbb64721b07f3f67167d5baebf224e240 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Tue, 17 May 2016 17:32:33 -0700 Subject: [PATCH] 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 Acked-by: Jesse Gross --- lib/dp-packet.h | 43 ++++++++++ lib/dpif-netdev.c | 153 ++++++++++++++++------------------- lib/dpif.c | 12 +-- lib/netdev.c | 36 ++++----- lib/netdev.h | 12 ++- lib/odp-execute.c | 10 ++- lib/odp-execute.h | 5 +- ofproto/ofproto-dpif-xlate.c | 5 +- 8 files changed, 154 insertions(+), 122 deletions(-) diff --git a/lib/dp-packet.h b/lib/dp-packet.h index 4a8b5aba9..118c84d3a 100644 --- a/lib/dp-packet.h +++ b/lib/dp-packet.h @@ -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 diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 387af675d..8bb18bcb8 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -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); } diff --git a/lib/dpif.c b/lib/dpif.c index 5037ac67f..20ce3b01c 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -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; } diff --git a/lib/netdev.c b/lib/netdev.c index 228b0688d..911e7c8fb 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -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; diff --git a/lib/netdev.h b/lib/netdev.h index f31b5654a..22e42093e 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -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 diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 7efd9ec1d..423962406 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -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() diff --git a/lib/odp-execute.h b/lib/odp-execute.h index c602bb4e4..7223fe82e 100644 --- a/lib/odp-execute.h +++ b/lib/odp-execute.h @@ -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); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index fec8b9cc8..9ccad5e61 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -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 -- 2.39.5