components/openvswitch/files/lib/dpif-solaris.c
changeset 7112 dab9beb5bc49
parent 6924 e8aaad6b5075
child 7237 c378a893371d
--- a/components/openvswitch/files/lib/dpif-solaris.c	Fri Oct 14 11:36:01 2016 -0700
+++ b/components/openvswitch/files/lib/dpif-solaris.c	Fri Oct 14 13:13:27 2016 -0700
@@ -39,11 +39,23 @@
 #include <zone.h>
 #include <libdllink.h>
 
+#ifndef	MAC_OFPORT_ARRAY
+/*
+ * Keeping a bitbucket of each containing 64-bits (uint64_t)
+ * for kernel ofports to effectively lookup a free ofport.
+ */
+#define	MAC_OFPORT_ARRAY		(MAC_OF_MAXPORT/64)
+#define	MAC_OFPORT_ARRAY_MASK		0x3F
+#define	MAC_OFPORT_ARRAY_SHIFT		6
+#endif
+
 VLOG_DEFINE_THIS_MODULE(dpif_solaris);
 
 static kstat2_handle_t	dpif_khandle;
 static boolean_t	kstat2_handle_initialized = B_FALSE;
 static struct ovs_mutex	kstat_mutex = OVS_MUTEX_INITIALIZER;
+static struct ovs_mutex dp_ports_bitvector_mutex = OVS_MUTEX_INITIALIZER;
+uint64_t dp_ports_bitvector[MAC_OFPORT_ARRAY];
 
 /* Datapath interface for the openvswitch Solaris kernel module. */
 struct dpif_solaris {
@@ -519,19 +531,6 @@
 	return (0);
 }
 
-static boolean_t
-port_no_used(struct dpif_solaris *dpif, uint32_t port_no)
-    OVS_REQ_WRLOCK(dp->port_rwlock)
-{
-	struct dpif_solaris_port *port;
-
-	HMAP_FOR_EACH(port, node, &dpif->ports) {
-		if (port->port_no == port_no)
-			return (true);
-	}
-	return (false);
-}
-
 /*
  * Choose an unused, non-zero port number and return it on success.
  * Return ODPP_NONE on failure.
@@ -539,22 +538,36 @@
  * need improvement. TBD
  */
 static odp_port_t
-choose_port(struct dpif_solaris *dpif)
-    OVS_REQ_WRLOCK(dp->port_rwlock)
+choose_port(void)
 {
 	uint32_t port_no;
-
+	uint64_t chk_bit;
+	ovs_mutex_lock(&dp_ports_bitvector_mutex);
 	for (port_no = PORT_PF_PACKET_UPLINK + 1;
 	    port_no < MAC_OF_MAXPORT; port_no++) {
-		if (port_no_used(dpif, port_no))
+		chk_bit = dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT];
+		if ((chk_bit & (1LL << (port_no & MAC_OFPORT_ARRAY_MASK))) > 0)
 			continue;
 
+		dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT] |=
+		    (1LL << (port_no & MAC_OFPORT_ARRAY_MASK));
+		ovs_mutex_unlock(&dp_ports_bitvector_mutex);
+		VLOG_DBG("dpif_solaris_choose_port: port no: %d", port_no);
 		return (u32_to_odp(port_no));
 	}
-
+	ovs_mutex_unlock(&dp_ports_bitvector_mutex);
 	return (ODPP_NONE);
 }
 
+static void
+reset_port(uint32_t port_no)
+{
+	ovs_mutex_lock(&dp_ports_bitvector_mutex);
+	dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT] &=
+	    ~(1LL << (port_no & MAC_OFPORT_ARRAY_MASK));
+	ovs_mutex_unlock(&dp_ports_bitvector_mutex);
+}
+
 static boolean_t
 pf_port_no_used(struct dpif_solaris *dpif, uint32_t pf_port_no)
 {
@@ -781,7 +794,7 @@
 	ovs_rwlock_wrlock(&dpif->port_rwlock);
 
 	if (*port_nop == ODPP_NONE) {
-		*port_nop = choose_port(dpif);
+		*port_nop = choose_port();
 		if (*port_nop == ODPP_NONE) {
 			error = EFBIG;
 			goto fail;
@@ -841,6 +854,9 @@
 	ovs_rwlock_unlock(&dpif->upcall_lock);
 	return (0);
 fail:
+	if (*port_nop != ODPP_NONE)
+		reset_port(odp_to_u32(*port_nop));
+
 	if (port != NULL) {
 		if (port->xfd != -1)
 			(void) close(port->xfd);
@@ -959,6 +975,8 @@
 	VLOG_DBG("dpif_solaris_port_del %s close xfd %d", port->name,
 	    port->xfd);
 
+	reset_port(port->port_no);
+
 	free(port->type);
 	free(port->name);
 	free(port->linkname);