@@ -257,6 +257,44 @@ meter_offload_del(ofproto_meter_id meter_id, struct ofputil_meter_stats *stats)
return 0;
}
+int
+netdev_offload_recv(struct dpif_upcall *upcall, struct ofpbuf *buf,
+ uint32_t handler_id)
+{
+ struct netdev_registered_flow_api *rfa;
+ int ret = EAGAIN;
+
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->recv) {
+ ret = rfa->flow_api->recv(upcall, buf, handler_id);
+ if (!ret) {
+ return 0;
+ }
+
+ if (ret == EAGAIN) {
+ VLOG_DBG_RL(&rl, "Failed to receive offload packet, %s, "
+ "type: %s", ovs_strerror(ret),
+ rfa->flow_api->type);
+ }
+ } else {
+ ret = EAGAIN;
+ }
+ }
+ return ret;
+}
+
+void
+netdev_offload_recv_wait(uint32_t handler_id)
+{
+ struct netdev_registered_flow_api *rfa;
+
+ CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
+ if (rfa->flow_api->recv_wait) {
+ rfa->flow_api->recv_wait(handler_id);
+ }
+ }
+}
+
int
netdev_flow_flush(struct netdev *netdev)
{
@@ -33,6 +33,7 @@ extern "C" {
struct dp_packet_batch;
struct dp_packet;
+struct dpif_upcall;
struct netdev_class;
struct netdev_rxq;
struct netdev_saved_flags;
@@ -162,6 +163,10 @@ void meter_offload_set(ofproto_meter_id, struct ofputil_meter_config *);
int meter_offload_get(ofproto_meter_id, struct ofputil_meter_stats *);
int meter_offload_del(ofproto_meter_id, struct ofputil_meter_stats *);
+int netdev_offload_recv(struct dpif_upcall *upcall, struct ofpbuf *buf,
+ uint32_t handler_id);
+void netdev_offload_recv_wait(uint32_t handler_id);
+
#ifdef __cplusplus
}
#endif