@@ -458,6 +458,24 @@ netdev_ports_flow_flush(const char *dpif_type)
ovs_rwlock_unlock(&netdev_hmap_rwlock);
}
+void
+netdev_ports_traverse(const char *dpif_type,
+ bool (*cb)(struct netdev *, odp_port_t, void *),
+ void *aux)
+{
+ struct port_to_netdev_data *data;
+
+ ovs_rwlock_rdlock(&netdev_hmap_rwlock);
+ HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
+ if (netdev_get_dpif_type(data->netdev) == dpif_type) {
+ if (cb(data->netdev, data->dpif_port.port_no, aux)) {
+ break;
+ }
+ }
+ }
+ ovs_rwlock_unlock(&netdev_hmap_rwlock);
+}
+
struct netdev_flow_dump **
netdev_ports_flow_dump_create(const char *dpif_type, int *ports, bool terse)
{
@@ -113,6 +113,14 @@ struct netdev *netdev_ports_get(odp_port_t port, const char *dpif_type);
int netdev_ports_remove(odp_port_t port, const char *dpif_type);
odp_port_t netdev_ifindex_to_odp_port(int ifindex);
+/* For each of the ports with dpif_type, call cb with the netdev and port
+ * number of the port, and an opaque user argument.
+ * The returned value is used to continue traversing upon false or stop if
+ * true.
+ */
+void netdev_ports_traverse(const char *dpif_type,
+ bool (*cb)(struct netdev *, odp_port_t, void *),
+ void *aux);
struct netdev_flow_dump **netdev_ports_flow_dump_create(
const char *dpif_type,
int *ports,