On May 23, 2014, at 11:37 AM, Ethan Jackson <et...@nicira.com> wrote:
> I don't totally get why we changed the prototype for > dp_netdev_flow_used() and dp_netdev_count_packets(). All the callers > seem to use the old semantics. You’re right, but next commits use the new semantics. I’ll merge the commits, if you think it’s clearer. > I'd replace the variable "int c" with "int cnt" to be consistent with > netdev_rxq_recv(). I also think it's a bit easier to tell what it is. > Sure, I’ll replace it. Thanks, Daniele > On Fri, May 23, 2014 at 11:04 AM, Daniele Di Proietto > <ddiproie...@vmware.com> wrote: >> This change in dpif-netdev allows faster packet receiving for devices >> like netdev-dpdk which implement batch receiving. >> >> Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com> >> --- >> This patchset allows dpif-netdev to process packets in batches. >> It boosts the performance of OVS with DPDK (forwarding a single unicast flow) >> from 1.9 Mpps to 3.3 Mpps in my tests. >> >> It is the first optimization step. There's still a lot of room for >> improvement >> until we hit 14.88 Mpps. >> >> Can you help review this, please, Pravin? >> --- >> lib/dpif-netdev.c | 101 >> +++++++++++++++++++++++++++++------------------------- >> 1 file changed, 54 insertions(+), 47 deletions(-) >> >> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >> index 91c83d6..d50452f 100644 >> --- a/lib/dpif-netdev.c >> +++ b/lib/dpif-netdev.c >> @@ -341,8 +341,8 @@ static void dp_netdev_execute_actions(struct dp_netdev >> *dp, >> struct pkt_metadata *, >> const struct nlattr *actions, >> size_t actions_len); >> -static void dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf >> *packet, >> - struct pkt_metadata *); >> +static void dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf >> **packets, >> + int c, odp_port_t port_no); >> >> static void dp_netdev_set_pmd_threads(struct dp_netdev *, int n); >> >> @@ -1747,17 +1747,12 @@ dp_netdev_process_rxq_port(struct dp_netdev *dp, >> struct dp_netdev_port *port, >> struct netdev_rxq *rxq) >> { >> - struct ofpbuf *packet[NETDEV_MAX_RX_BATCH]; >> + struct ofpbuf *packets[NETDEV_MAX_RX_BATCH]; >> int error, c; >> >> - error = netdev_rxq_recv(rxq, packet, &c); >> + error = netdev_rxq_recv(rxq, packets, &c); >> if (!error) { >> - struct pkt_metadata md = PKT_METADATA_INITIALIZER(port->port_no); >> - int i; >> - >> - for (i = 0; i < c; i++) { >> - dp_netdev_port_input(dp, packet[i], &md); >> - } >> + dp_netdev_port_input(dp, packets, c, port->port_no); >> } else if (error != EAGAIN && error != EOPNOTSUPP) { >> static struct vlog_rate_limit rl >> = VLOG_RATE_LIMIT_INIT(1, 5); >> @@ -1954,7 +1949,7 @@ dp_netdev_flow_stats_new_cb(void) >> >> static void >> dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow, >> - const struct ofpbuf *packet, >> + int c, int size, >> const struct miniflow *key) >> { >> uint16_t tcp_flags = miniflow_get_tcp_flags(key); >> @@ -1966,8 +1961,8 @@ dp_netdev_flow_used(struct dp_netdev_flow *netdev_flow, >> >> ovs_mutex_lock(&bucket->mutex); >> bucket->used = MAX(now, bucket->used); >> - bucket->packet_count++; >> - bucket->byte_count += ofpbuf_size(packet); >> + bucket->packet_count += c; >> + bucket->byte_count += size; >> bucket->tcp_flags |= tcp_flags; >> ovs_mutex_unlock(&bucket->mutex); >> } >> @@ -1981,61 +1976,73 @@ dp_netdev_stats_new_cb(void) >> } >> >> static void >> -dp_netdev_count_packet(struct dp_netdev *dp, enum dp_stat_type type) >> +dp_netdev_count_packet(struct dp_netdev *dp, enum dp_stat_type type, int >> packets) >> { >> struct dp_netdev_stats *bucket; >> >> bucket = ovsthread_stats_bucket_get(&dp->stats, dp_netdev_stats_new_cb); >> ovs_mutex_lock(&bucket->mutex); >> - bucket->n[type]++; >> + bucket->n[type] += packets; >> ovs_mutex_unlock(&bucket->mutex); >> } >> >> static void >> -dp_netdev_input(struct dp_netdev *dp, struct ofpbuf *packet, >> +dp_netdev_input(struct dp_netdev *dp, struct ofpbuf **packets, int c, >> struct pkt_metadata *md) >> { >> - struct dp_netdev_flow *netdev_flow; >> - struct { >> - struct miniflow flow; >> - uint32_t buf[FLOW_U32S]; >> - } key; >> + int i; >> >> - if (ofpbuf_size(packet) < ETH_HEADER_LEN) { >> - ofpbuf_delete(packet); >> - return; >> - } >> - miniflow_initialize(&key.flow, key.buf); >> - miniflow_extract(packet, md, &key.flow); >> + for (i = 0; i < c; i++) { >> + struct dp_netdev_flow *netdev_flow; >> + struct { >> + struct miniflow flow; >> + uint32_t buf[FLOW_U32S]; >> + } key; >> >> - netdev_flow = dp_netdev_lookup_flow(dp, &key.flow); >> - if (netdev_flow) { >> - struct dp_netdev_actions *actions; >> + if (ofpbuf_size(packets[i]) < ETH_HEADER_LEN) { >> + ofpbuf_delete(packets[i]); >> + continue; >> + } >> + miniflow_initialize(&key.flow, key.buf); >> + miniflow_extract(packets[i], &md[i], &key.flow); >> + >> + netdev_flow = dp_netdev_lookup_flow(dp, &key.flow); >> >> - dp_netdev_flow_used(netdev_flow, packet, &key.flow); >> + if (netdev_flow) { >> + struct dp_netdev_actions *actions; >> + >> + dp_netdev_flow_used(netdev_flow, 1, ofpbuf_size(packets[i]), >> &key.flow); >> >> - actions = dp_netdev_flow_get_actions(netdev_flow); >> - dp_netdev_execute_actions(dp, &key.flow, packet, true, md, >> - actions->actions, actions->size); >> - dp_netdev_count_packet(dp, DP_STAT_HIT); >> - } else if (dp->handler_queues) { >> - dp_netdev_count_packet(dp, DP_STAT_MISS); >> - dp_netdev_output_userspace(dp, packet, >> - miniflow_hash_5tuple(&key.flow, 0) >> - % dp->n_handlers, >> - DPIF_UC_MISS, &key.flow, NULL); >> - ofpbuf_delete(packet); >> + actions = dp_netdev_flow_get_actions(netdev_flow); >> + dp_netdev_execute_actions(dp, &key.flow, packets[i], true, >> &md[i], >> + actions->actions, actions->size); >> + dp_netdev_count_packet(dp, DP_STAT_HIT, 1); >> + } else if (dp->handler_queues) { >> + dp_netdev_count_packet(dp, DP_STAT_MISS, 1); >> + dp_netdev_output_userspace(dp, packets[i], >> + miniflow_hash_5tuple(&key.flow, 0) >> + % dp->n_handlers, >> + DPIF_UC_MISS, &key.flow, NULL); >> + ofpbuf_delete(packets[i]); >> + } >> } >> } >> >> static void >> -dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet, >> - struct pkt_metadata *md) >> +dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf **packets, >> + int c, odp_port_t port_no) >> { >> uint32_t *recirc_depth = recirc_depth_get(); >> + struct pkt_metadata md[c]; >> + >> + int i; >> + >> + for (i = 0; i < c; i++) { >> + md[i] = PKT_METADATA_INITIALIZER(port_no); >> + } >> >> *recirc_depth = 0; >> - dp_netdev_input(dp, packet, md); >> + dp_netdev_input(dp, packets, c, md); >> } >> >> static int >> @@ -2086,7 +2093,7 @@ dp_netdev_output_userspace(struct dp_netdev *dp, >> struct ofpbuf *packet, >> >> error = 0; >> } else { >> - dp_netdev_count_packet(dp, DP_STAT_LOST); >> + dp_netdev_count_packet(dp, DP_STAT_LOST, 1); >> error = ENOBUFS; >> } >> ovs_mutex_unlock(&q->mutex); >> @@ -2167,7 +2174,7 @@ dp_execute_cb(void *aux_, struct ofpbuf *packet, >> recirc_md.recirc_id = nl_attr_get_u32(a); >> >> (*depth)++; >> - dp_netdev_input(aux->dp, recirc_packet, &recirc_md); >> + dp_netdev_input(aux->dp, &recirc_packet, 1, &recirc_md); >> (*depth)--; >> >> break; >> -- >> 2.0.0.rc0 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://urldefense.proofpoint.com/v1/url?u=http://openvswitch.org/mailman/listinfo/dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=MV9BdLjtFIdhBDBaw5z%2BU6SSA2gAfY4L%2F1HCy3VjlKU%3D%0A&m=FEBCo6DqETk%2BK8mcS0VJccwzQeyWNa8uslMFveNSCNY%3D%0A&s=62888bd069886bc59f3fa5b81d478a389a6664de0c98c010aa1fd5a61be1e3f9 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev