In thread handler 0, add netdev offload recv in normal recv upcalls. To avoid starvation, introduce a flag to alternate the order of receiving normal upcalls and offload upcalls based on that flag.
Add similar change for recv_wait. Signed-off-by: Chris Mi <[email protected]> Reviewed-by: Roi Dayan <[email protected]> --- lib/dpif-netlink.c | 46 ++++++++++++++++++++++++++++++++--- ofproto/ofproto-dpif-upcall.c | 23 +++++++++++++++--- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 586fb8893..9f67db1be 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -201,6 +201,12 @@ struct dpif_handler { struct nl_sock *sock; /* Each handler thread holds one netlink socket. */ + /* Thread handler 0 deals with both netdev offload recv and normal + * recv upcalls. To avoid starvation, introduce a flag to alternate + * the order. + */ + bool recv_offload_first; + #ifdef _WIN32 /* Pool of sockets. */ struct dpif_windows_vport_sock *vport_sock_pool; @@ -3130,13 +3136,12 @@ dpif_netlink_recv_vport_dispatch(struct dpif_netlink *dpif, #endif static int -dpif_netlink_recv(struct dpif *dpif_, uint32_t handler_id, - struct dpif_upcall *upcall, struct ofpbuf *buf) +dpif_netlink_recv__(struct dpif *dpif_, uint32_t handler_id, + struct dpif_upcall *upcall, struct ofpbuf *buf) { struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); int error; - fat_rwlock_rdlock(&dpif->upcall_lock); #ifdef _WIN32 error = dpif_netlink_recv_windows(dpif, handler_id, upcall, buf); #else @@ -3147,6 +3152,38 @@ dpif_netlink_recv(struct dpif *dpif_, uint32_t handler_id, handler_id, upcall, buf); } #endif + + return error; +} + +static int +dpif_netlink_recv(struct dpif *dpif_, uint32_t handler_id, + struct dpif_upcall *upcall, struct ofpbuf *buf) +{ + struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); + struct dpif_handler *handler; + int error; + + fat_rwlock_rdlock(&dpif->upcall_lock); + if (handler_id) { + error = dpif_netlink_recv__(dpif_, handler_id, upcall, buf); + fat_rwlock_unlock(&dpif->upcall_lock); + return error; + } + + handler = &dpif->handlers[handler_id]; + if (handler->recv_offload_first) { + error = netdev_offload_recv(upcall, buf); + if (error == EAGAIN) { + error = dpif_netlink_recv__(dpif_, handler_id, upcall, buf); + } + } else { + error = dpif_netlink_recv__(dpif_, handler_id, upcall, buf); + if (error == EAGAIN) { + error = netdev_offload_recv(upcall, buf); + } + } + handler->recv_offload_first = !handler->recv_offload_first; fat_rwlock_unlock(&dpif->upcall_lock); return error; @@ -3211,6 +3248,9 @@ dpif_netlink_recv_wait(struct dpif *dpif_, uint32_t handler_id) } else { dpif_netlink_recv_wait_vport_dispatch(dpif, handler_id); } + if (handler_id == 0) { + netdev_offload_recv_wait(); + } #endif fat_rwlock_unlock(&dpif->upcall_lock); } diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index fc94078cb..273b576bd 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -840,10 +840,25 @@ recv_upcalls(struct handler *handler) break; } - upcall->fitness = odp_flow_key_to_flow(dupcall->key, dupcall->key_len, - flow, NULL); - if (upcall->fitness == ODP_FIT_ERROR) { - goto free_dupcall; + /* If it is normal upcalls, datapath will provide key and key_len + * to construct flow. But for netdev offload upcalls, key and + * key_len are not available. Construct partial flow using available + * info. + */ + if (dupcall->key && dupcall->key_len) { + upcall->fitness = odp_flow_key_to_flow(dupcall->key, + dupcall->key_len, + flow, NULL); + if (upcall->fitness == ODP_FIT_ERROR) { + goto free_dupcall; + } + } else { + memset(flow, 0, sizeof *flow); + if (dupcall->in_tun) { + memcpy(&flow->tunnel, dupcall->in_tun, sizeof flow->tunnel); + } + flow->in_port.odp_port = + netdev_ifindex_to_odp_port(dupcall->iifindex); } if (dupcall->mru) { -- 2.26.3 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
