37 #include "vlog.h" |
37 #include "vlog.h" |
38 #include <netpacket/packet.h> |
38 #include <netpacket/packet.h> |
39 #include <zone.h> |
39 #include <zone.h> |
40 #include <libdllink.h> |
40 #include <libdllink.h> |
41 |
41 |
|
42 #ifndef MAC_OFPORT_ARRAY |
|
43 /* |
|
44 * Keeping a bitbucket of each containing 64-bits (uint64_t) |
|
45 * for kernel ofports to effectively lookup a free ofport. |
|
46 */ |
|
47 #define MAC_OFPORT_ARRAY (MAC_OF_MAXPORT/64) |
|
48 #define MAC_OFPORT_ARRAY_MASK 0x3F |
|
49 #define MAC_OFPORT_ARRAY_SHIFT 6 |
|
50 #endif |
|
51 |
42 VLOG_DEFINE_THIS_MODULE(dpif_solaris); |
52 VLOG_DEFINE_THIS_MODULE(dpif_solaris); |
43 |
53 |
44 static kstat2_handle_t dpif_khandle; |
54 static kstat2_handle_t dpif_khandle; |
45 static boolean_t kstat2_handle_initialized = B_FALSE; |
55 static boolean_t kstat2_handle_initialized = B_FALSE; |
46 static struct ovs_mutex kstat_mutex = OVS_MUTEX_INITIALIZER; |
56 static struct ovs_mutex kstat_mutex = OVS_MUTEX_INITIALIZER; |
|
57 static struct ovs_mutex dp_ports_bitvector_mutex = OVS_MUTEX_INITIALIZER; |
|
58 uint64_t dp_ports_bitvector[MAC_OFPORT_ARRAY]; |
47 |
59 |
48 /* Datapath interface for the openvswitch Solaris kernel module. */ |
60 /* Datapath interface for the openvswitch Solaris kernel module. */ |
49 struct dpif_solaris { |
61 struct dpif_solaris { |
50 struct dpif dpif; |
62 struct dpif dpif; |
51 dladm_handle_t dh; |
63 dladm_handle_t dh; |
517 port->name, port->port_no); |
529 port->name, port->port_no); |
518 |
530 |
519 return (0); |
531 return (0); |
520 } |
532 } |
521 |
533 |
522 static boolean_t |
|
523 port_no_used(struct dpif_solaris *dpif, uint32_t port_no) |
|
524 OVS_REQ_WRLOCK(dp->port_rwlock) |
|
525 { |
|
526 struct dpif_solaris_port *port; |
|
527 |
|
528 HMAP_FOR_EACH(port, node, &dpif->ports) { |
|
529 if (port->port_no == port_no) |
|
530 return (true); |
|
531 } |
|
532 return (false); |
|
533 } |
|
534 |
|
535 /* |
534 /* |
536 * Choose an unused, non-zero port number and return it on success. |
535 * Choose an unused, non-zero port number and return it on success. |
537 * Return ODPP_NONE on failure. |
536 * Return ODPP_NONE on failure. |
538 * The current approach to choose unused port number is quite inefficient, |
537 * The current approach to choose unused port number is quite inefficient, |
539 * need improvement. TBD |
538 * need improvement. TBD |
540 */ |
539 */ |
541 static odp_port_t |
540 static odp_port_t |
542 choose_port(struct dpif_solaris *dpif) |
541 choose_port(void) |
543 OVS_REQ_WRLOCK(dp->port_rwlock) |
|
544 { |
542 { |
545 uint32_t port_no; |
543 uint32_t port_no; |
546 |
544 uint64_t chk_bit; |
|
545 ovs_mutex_lock(&dp_ports_bitvector_mutex); |
547 for (port_no = PORT_PF_PACKET_UPLINK + 1; |
546 for (port_no = PORT_PF_PACKET_UPLINK + 1; |
548 port_no < MAC_OF_MAXPORT; port_no++) { |
547 port_no < MAC_OF_MAXPORT; port_no++) { |
549 if (port_no_used(dpif, port_no)) |
548 chk_bit = dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT]; |
|
549 if ((chk_bit & (1LL << (port_no & MAC_OFPORT_ARRAY_MASK))) > 0) |
550 continue; |
550 continue; |
551 |
551 |
|
552 dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT] |= |
|
553 (1LL << (port_no & MAC_OFPORT_ARRAY_MASK)); |
|
554 ovs_mutex_unlock(&dp_ports_bitvector_mutex); |
|
555 VLOG_DBG("dpif_solaris_choose_port: port no: %d", port_no); |
552 return (u32_to_odp(port_no)); |
556 return (u32_to_odp(port_no)); |
553 } |
557 } |
554 |
558 ovs_mutex_unlock(&dp_ports_bitvector_mutex); |
555 return (ODPP_NONE); |
559 return (ODPP_NONE); |
|
560 } |
|
561 |
|
562 static void |
|
563 reset_port(uint32_t port_no) |
|
564 { |
|
565 ovs_mutex_lock(&dp_ports_bitvector_mutex); |
|
566 dp_ports_bitvector[port_no >> MAC_OFPORT_ARRAY_SHIFT] &= |
|
567 ~(1LL << (port_no & MAC_OFPORT_ARRAY_MASK)); |
|
568 ovs_mutex_unlock(&dp_ports_bitvector_mutex); |
556 } |
569 } |
557 |
570 |
558 static boolean_t |
571 static boolean_t |
559 pf_port_no_used(struct dpif_solaris *dpif, uint32_t pf_port_no) |
572 pf_port_no_used(struct dpif_solaris *dpif, uint32_t pf_port_no) |
560 { |
573 { |
779 } |
792 } |
780 ovs_rwlock_wrlock(&dpif->upcall_lock); |
793 ovs_rwlock_wrlock(&dpif->upcall_lock); |
781 ovs_rwlock_wrlock(&dpif->port_rwlock); |
794 ovs_rwlock_wrlock(&dpif->port_rwlock); |
782 |
795 |
783 if (*port_nop == ODPP_NONE) { |
796 if (*port_nop == ODPP_NONE) { |
784 *port_nop = choose_port(dpif); |
797 *port_nop = choose_port(); |
785 if (*port_nop == ODPP_NONE) { |
798 if (*port_nop == ODPP_NONE) { |
786 error = EFBIG; |
799 error = EFBIG; |
787 goto fail; |
800 goto fail; |
788 } |
801 } |
789 } |
802 } |
839 hmap_insert(&dpif->ports, &port->node, hash_odp_port(port->port_no)); |
852 hmap_insert(&dpif->ports, &port->node, hash_odp_port(port->port_no)); |
840 ovs_rwlock_unlock(&dpif->port_rwlock); |
853 ovs_rwlock_unlock(&dpif->port_rwlock); |
841 ovs_rwlock_unlock(&dpif->upcall_lock); |
854 ovs_rwlock_unlock(&dpif->upcall_lock); |
842 return (0); |
855 return (0); |
843 fail: |
856 fail: |
|
857 if (*port_nop != ODPP_NONE) |
|
858 reset_port(odp_to_u32(*port_nop)); |
|
859 |
844 if (port != NULL) { |
860 if (port != NULL) { |
845 if (port->xfd != -1) |
861 if (port->xfd != -1) |
846 (void) close(port->xfd); |
862 (void) close(port->xfd); |
847 dpif_solaris_destroy_port_channel(dpif, port); |
863 dpif_solaris_destroy_port_channel(dpif, port); |
848 free(port->name); |
864 free(port->name); |