Changeset 29708 in vbox for trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c
- Timestamp:
- May 20, 2010 5:00:05 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/solaris/VBoxNetFltBow-solaris.c
r29691 r29708 29 29 #include <iprt/err.h> 30 30 #include <iprt/string.h> 31 #include <iprt/rand.h> 31 32 #include <iprt/net.h> 32 33 #include <iprt/spinlock.h> 34 #include <iprt/mem.h> 33 35 34 36 #include <sys/types.h> … … 77 79 /** Debugging switch for using symbols in kmdb */ 78 80 # define LOCAL static 81 /** VBOXNETFLTVNIC::u32Magic */ 82 # define VBOXNETFLTVNIC_MAGIC 0x0ddfaced 79 83 80 84 #if defined(DEBUG_ramshankar) … … 183 187 typedef struct VBOXNETFLTVNIC 184 188 { 185 void *pvIf; /* The VirtualBox interface */ 186 mac_handle_t hInterface; /* The lower MAC handle */ 187 datalink_id_t hLinkId; /* The link ID */ 188 mac_client_handle_t hClient; /* Client handle */ 189 mac_unicast_handle_t hUnicast; /* Unicast address handle */ 190 mac_promisc_handle_t hPromiscuous; /* Promiscuous handle */ 191 list_node_t hNode; /* Handle to the next VNIC in the list */ 189 uint32_t u32Magic; /* Magic number (VBOXNETFLTVNIC_MAGIC) */ 190 bool fCreated; /* Whether we created the VNIC or not */ 191 void *pvIf; /* The VirtualBox interface */ 192 mac_handle_t hInterface; /* The lower MAC handle */ 193 datalink_id_t hLinkId; /* The link ID */ 194 mac_client_handle_t hClient; /* Client handle */ 195 mac_unicast_handle_t hUnicast; /* Unicast address handle */ 196 mac_promisc_handle_t hPromiscuous; /* Promiscuous handle */ 197 char szName[128]; /* The VNIC name */ 198 list_node_t hNode; /* Handle to the next VNIC in the list */ 192 199 } VBOXNETFLTVNIC; 193 200 typedef struct VBOXNETFLTVNIC *PVBOXNETFLTVNIC; … … 206 213 207 214 /******************************************************************************* 208 * Internal Function 215 * Internal Functions * 209 216 *******************************************************************************/ 210 217 LOCAL mblk_t *vboxNetFltSolarisMBlkFromSG(PVBOXNETFLTINS pThis, PINTNETSG pSG, uint32_t fDst); 211 218 LOCAL unsigned vboxNetFltSolarisMBlkCalcSGSegs(PVBOXNETFLTINS pThis, mblk_t *pMsg); 212 219 LOCAL int vboxNetFltSolarisMBlkToSG(PVBOXNETFLTINS pThis, mblk_t *pMsg, PINTNETSG pSG, unsigned cSegs, uint32_t fSrc); 213 214 LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery);215 LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis);216 220 LOCAL void vboxNetFltSolarisRecv(void *pvData, mac_resource_handle_t hResource, mblk_t *pMsg, boolean_t fLoopback); 221 LOCAL void vboxNetFltSolarisAnalyzeMBlk(mblk_t *pMsg); 222 LOCAL void vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis); 223 LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC); 224 LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void); 225 LOCAL void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC); 226 LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC); 227 LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC); 217 228 218 229 … … 681 692 682 693 694 LOCAL void vboxNetFltSolarisReportInfo(PVBOXNETFLTINS pThis) 695 { 696 if (!pThis->u.s.fReportedInfo) 697 { 698 if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) 699 { 700 Assert(pThis->pSwitchPort); 701 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); 702 pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */ 703 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); 704 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); 705 vboxNetFltRelease(pThis, true /*fBusy*/); 706 pThis->u.s.fReportedInfo = true; 707 } 708 } 709 } 710 711 712 LOCAL int vboxNetFltSolarisInitVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC pVNIC) 713 { 714 /* 715 * Some paranoia. 716 */ 717 AssertReturn(pThis, VERR_INVALID_PARAMETER); 718 AssertReturn(pVNIC, VERR_INVALID_PARAMETER); 719 AssertReturn(pVNIC->hInterface, VERR_INVALID_POINTER); 720 AssertReturn(pVNIC->hLinkId, VERR_INVALID_POINTER); 721 AssertReturn(!pVNIC->hClient, VERR_INVALID_HANDLE); 722 723 int rc = mac_client_open(pVNIC->hInterface, &pVNIC->hClient, 724 NULL, /* name of this client */ 725 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */ 726 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */ 727 ); 728 if (RT_LIKELY(!rc)) 729 { 730 /* 731 * Set the RX callback. 732 */ 733 mac_diag_t Diag = MAC_DIAG_NONE; 734 rc = mac_unicast_add_set_rx(pVNIC->hClient, 735 NULL /* MAC address, use existing VNIC address */, 736 MAC_UNICAST_PRIMARY | /* Use Primary address of the VNIC */ 737 MAC_UNICAST_NODUPCHECK, /* Don't fail for conflicting MAC/VLAN-id combinations */ 738 &pVNIC->hUnicast, 739 0 /* VLAN-id */, 740 &Diag, 741 vboxNetFltSolarisRecv, /* RX callback */ 742 pThis /* callback private data */ 743 ); 744 if (RT_LIKELY(!rc)) 745 { 746 if (!pThis->u.s.fReportedInfo) 747 { 748 /* 749 * Obtain the MAC address of the underlying physical interface. 750 */ 751 mac_handle_t hLowerMac = mac_get_lower_mac_handle(pVNIC->hInterface); 752 if (RT_LIKELY(hLowerMac)) 753 { 754 mac_unicast_primary_get(hLowerMac, (uint8_t *)pThis->u.s.MacAddr.au8); 755 vboxNetFltSolarisReportInfo(pThis); 756 } 757 else 758 { 759 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to get lower MAC handle for '%s'\n", pThis->szName)); 760 rc = ENODEV; 761 } 762 } 763 764 if (!rc) 765 { 766 Assert(pVNIC->hClient); 767 Assert(pVNIC->hInterface); 768 Assert(pVNIC->hLinkId); 769 LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance successfully initialized VNIC '%s'\n", pVNIC->szName)); 770 return 0; 771 } 772 773 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast); 774 mac_rx_clear(pVNIC->hClient); 775 pVNIC->hUnicast = NULL; 776 } 777 else 778 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to set RX callback. rc=%d Diag=%d\n", rc, Diag)); 779 780 mac_client_close(pVNIC->hClient, 0 /* flags */); 781 pVNIC->hClient = NULL; 782 } 783 else 784 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to open mac client for '%s' rc=%d\n", pThis->szName, rc)); 785 786 return RTErrConvertFromErrno(rc); 787 } 788 789 790 LOCAL PVBOXNETFLTVNIC vboxNetFltSolarisAllocVNIC(void) 791 { 792 PVBOXNETFLTVNIC pVNIC = RTMemAlloc(sizeof(VBOXNETFLTVNIC)); 793 if (RT_UNLIKELY(!pVNIC)) 794 return NULL; 795 796 pVNIC->u32Magic = VBOXNETFLTVNIC_MAGIC; 797 pVNIC->fCreated = false; 798 pVNIC->pvIf = NULL; 799 pVNIC->hInterface = NULL; 800 pVNIC->hLinkId = DATALINK_INVALID_LINKID; 801 pVNIC->hClient = NULL; 802 pVNIC->hUnicast = NULL; 803 pVNIC->hPromiscuous = NULL; 804 RT_ZERO(pVNIC->szName); 805 list_link_init(&pVNIC->hNode); 806 return pVNIC; 807 } 808 809 810 LOCAL void vboxNetFltSolarisFreeVNIC(PVBOXNETFLTVNIC pVNIC) 811 { 812 if (pVNIC) 813 RTMemFree(pVNIC); 814 } 815 816 683 817 /** 684 818 * Destroy a created VNIC. … … 686 820 * @param pThis The VM connection instance. 687 821 */ 688 LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTINS pThis) 689 { 690 #if 0 691 if (pThis->u.s.fCreatedVNIC) 692 { 693 vnic_delete(pThis->u.s.VNICLinkId, 0 /* Flags */); 694 pThis->u.s.VNICLinkId = DATALINK_INVALID_LINKID; 695 pThis->u.s.fCreatedVNIC = false; 696 } 697 #endif 822 LOCAL void vboxNetFltSolarisDestroyVNIC(PVBOXNETFLTVNIC pVNIC) 823 { 824 if (pVNIC) 825 { 826 if (pVNIC->hPromiscuous) 827 { 828 mac_promisc_remove(pVNIC->hPromiscuous); 829 pVNIC->hPromiscuous = NULL; 830 } 831 832 if (pVNIC->hClient) 833 { 834 if (pVNIC->hUnicast) 835 { 836 mac_unicast_remove(pVNIC->hClient, pVNIC->hUnicast); 837 pVNIC->hUnicast = NULL; 838 } 839 840 mac_rx_clear(pVNIC->hClient); 841 842 mac_client_close(pVNIC->hClient, 0 /* fFlags */); 843 pVNIC->hClient = NULL; 844 } 845 846 if (pVNIC->hInterface) 847 { 848 mac_close(pVNIC->hInterface); 849 pVNIC->hInterface = NULL; 850 } 851 852 if (pVNIC->fCreated) 853 { 854 vnic_delete(pVNIC->hLinkId, 0 /* Flags */); 855 pVNIC->hLinkId = DATALINK_INVALID_LINKID; 856 pVNIC->fCreated = false; 857 } 858 } 698 859 } 699 860 … … 703 864 * 704 865 * @param pThis The VM connection instance. 866 * @param ppVNIC Where to store the created VNIC. 705 867 * 706 868 * @returns corresponding VBox error code. 707 869 */ 708 LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis) 709 { 710 #if 0 870 LOCAL int vboxNetFltSolarisCreateVNIC(PVBOXNETFLTINS pThis, PVBOXNETFLTVNIC *ppVNIC) 871 { 711 872 LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC pThis=%p\n", pThis)); 712 873 713 char szVNICName[sizeof(VBOXFLT_VNIC_NAME) + 32]; 714 RTStrPrintf(szVNICName, sizeof(szVNICName), "%s%d", VBOXFLT_VNIC_NAME, pThis->u.s.uInstance); 715 716 /* -XXX- @todo remove hardcoded Guest MAC address, should be sent from guest later. */ 874 AssertReturn(pThis, VERR_INVALID_POINTER); 875 AssertReturn(ppVNIC, VERR_INVALID_POINTER); 876 877 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC(); 878 if (RT_UNLIKELY(!pVNIC)) 879 return VERR_NO_MEMORY; 880 881 AssertCompile(sizeof(pVNIC->szName) > sizeof(VBOXFLT_VNIC_NAME) + 64); 882 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s%RU64", VBOXFLT_VNIC_NAME, pThis->u.s.uInstance); 883 884 /* 885 * Set a random MAC address. 886 */ 717 887 RTMAC GuestMac; 718 888 GuestMac.au8[0] = 0x08; 719 889 GuestMac.au8[1] = 0x00; 720 890 GuestMac.au8[2] = 0x27; 721 GuestMac.au8[3] = 0xFE; 722 GuestMac.au8[4] = 0x21; 723 GuestMac.au8[5] = 0x03; 891 RTRandBytes(&GuestMac.au8[3], 3); 724 892 725 893 AssertCompile(sizeof(RTMAC) <= MAXMACADDRLEN); 726 uchar_t MacAddr[MAXMACADDRLEN];727 bzero(MacAddr, sizeof(MacAddr));728 bcopy(GuestMac.au8, MacAddr, RT_MIN(sizeof(GuestMac), sizeof(MacAddr)));729 894 730 895 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED; 731 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE; 732 int MacSlot = 0; 733 int MacLen = sizeof(GuestMac); 734 uint32_t fFlags = 0; /* no VNIC_IOC_CREATE_NODUPCHECK */ 735 int rc = vnic_create(szVNICName, pThis->szName, &AddrType, &MacLen, MacAddr, &MacSlot, 0 /* Mac-Prefix Length */, 0 /* VLAN-ID */, 736 fFlags, &pThis->u.s.VNICLinkId, &Diag, NULL /* Reserved */); 896 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE; 897 int MacSlot = 0; 898 int MacLen = sizeof(GuestMac); 899 uint32_t fFlags = 0; /* @todo it should be VNIC_IOC_CREATE_NODUPCHECK */ 900 901 int rc = vnic_create(pVNIC->szName, pThis->szName, &AddrType, &MacLen, GuestMac.au8, &MacSlot, 0 /* Mac-Prefix Length */, 0 /* VLAN-ID */, 902 fFlags, &pVNIC->hLinkId, &Diag, NULL /* Reserved */); 737 903 if (!rc) 738 904 { 739 pThis->u.s.fCreatedVNIC = true; 740 pThis->u.s.uInstance++; 905 pVNIC->fCreated = true; 741 906 742 907 /* 743 908 * Now try opening the created VNIC. 744 909 */ 745 rc = mac_open_by_linkid(p This->u.s.VNICLinkId, &pThis->u.s.hInterface);910 rc = mac_open_by_linkid(pVNIC->hLinkId, &pVNIC->hInterface); 746 911 if (!rc) 747 912 { 748 Assert(pThis->u.s.hInterface); 749 LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC successfully created VNIC '%s' over '%s'\n", szVNICName, pThis->szName)); 750 return VINF_SUCCESS; 751 } 752 else 753 { 754 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to open VNIC '%s' over '%s'. rc=%d\n", szVNICName, 755 pThis->szName, rc)); 756 } 757 758 vboxNetFltSolarisDestroyVNIC(pThis); 759 rc = VERR_INTNET_FLT_IF_FAILED; 760 } 761 else 762 { 763 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed! rc=%d Diag=%d\n", rc, (int)Diag)); 764 rc = VERR_INTNET_FLT_IF_FAILED; 765 } 766 767 return rc; 768 #endif 769 } 770 771 772 /** 773 * Attach to the network interface. 774 * 775 * @param pThis The VM connection instance. 776 * @param fRediscovery Whether this is a rediscovery attempt after disconnect. 777 * 778 * @returns corresponding VBox error code. 779 */ 780 LOCAL int vboxNetFltSolarisAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery) 781 { 782 #if 0 783 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface pThis=%p fRediscovery=%d\n", pThis, fRediscovery)); 784 785 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 786 787 /* 788 * Open the underlying interface (lower MAC) and get it's handle. 789 */ 790 int rc = mac_open_by_linkname(pThis->szName, &pThis->u.s.hInterface); 791 if (RT_LIKELY(!rc)) 792 { 793 /* 794 * If this is not a VNIC, create a VNIC and open it instead. 795 */ 796 rc = mac_is_vnic(pThis->u.s.hInterface); 797 if (!rc) 798 { 799 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface '%s' is not a VNIC. Creating one.\n", pThis->szName)); 800 801 mac_close(pThis->u.s.hInterface); 802 pThis->u.s.hInterface = NULL; 803 rc = vboxNetFltSolarisCreateVNIC(pThis); 804 } 805 else 806 rc = VINF_SUCCESS; 807 808 /* 809 * At this point "hInterface" should be a handle to a VNIC, we no longer would deal with physical interface 810 * if it has been passed by the user. 811 */ 812 if (RT_SUCCESS(rc)) 813 { 814 /* 815 * Obtain the MAC address of the interface. 816 */ 817 Assert(pThis->u.s.hInterface); 818 AssertCompile(sizeof(RTMAC) == ETHERADDRL); 819 mac_unicast_primary_get(pThis->u.s.hInterface, (uint8_t *)&pThis->u.s.MacAddr.au8); 820 821 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface MAC address of %s is %.*Rhxs\n", pThis->szName, 822 sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); 823 824 /** @todo Obtain the MTU size using mac_sdu_get() */ 825 /** @todo Obtain capabilities (hardware checksum etc.) using mac_capab_get() */ 826 827 /* 828 * Open a client connection to the lower MAC interface. 829 */ 830 rc = mac_client_open(pThis->u.s.hInterface, &pThis->u.s.hClient, 831 NULL, /* name of this client */ 832 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */ 833 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */ 834 ); 913 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC); 835 914 if (RT_LIKELY(!rc)) 836 915 { 837 /** @todo -XXX- if possible we must move unicast_add and rx_set to when the Guest advertises it's MAC to us. */ 838 839 /* 840 * Set a unicast address for this client and the packet receive callback. 841 * We want to use the primary unicast address of the underlying interface (VNIC) hence we pass NULL. 842 * Also we don't really set the RX function here, this is done when we activate promiscuous mode. 843 */ 844 mac_diag_t MacDiag; 845 rc = mac_unicast_add(pThis->u.s.hClient, NULL /* MAC Address */, 846 MAC_UNICAST_PRIMARY | MAC_UNICAST_STRIP_DISABLE | 847 MAC_UNICAST_DISABLE_TX_VID_CHECK | MAC_UNICAST_NODUPCHECK | MAC_UNICAST_HW, 848 &pThis->u.s.hUnicast, 0 /* VLAN id */, &MacDiag); 849 if (!rc) 850 { 851 if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) 852 { 853 Assert(pThis->pSwitchPort); 854 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); 855 pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */ 856 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); 857 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); 858 vboxNetFltRelease(pThis, true /*fBusy*/); 859 } 860 861 /* 862 * If the user passed in the VNIC, we need to obtain the datalink ID now. 863 */ 864 if (pThis->u.s.fCreatedVNIC == false) 865 rc = dls_mgmt_get_linkid(pThis->szName, &pThis->u.s.VNICLinkId); 866 867 if (!rc) 868 { 869 /* 870 * Modify the MAC address of the VNIC to match the guest's MAC address 871 */ 872 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface success!\n")); 873 874 RTMAC GuestMac; 875 GuestMac.au8[0] = 0x08; 876 GuestMac.au8[1] = 0x00; 877 GuestMac.au8[2] = 0x27; 878 GuestMac.au8[3] = 0xFE; 879 GuestMac.au8[4] = 0x21; 880 GuestMac.au8[5] = 0x03; 881 882 uchar_t MacAddr[MAXMACADDRLEN]; 883 bcopy(GuestMac.au8, MacAddr, sizeof(GuestMac)); 884 885 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED; 886 vnic_ioc_diag_t Result = VNIC_IOC_DIAG_NONE; 887 int MacSlot = 0; 888 int MacLen = sizeof(GuestMac); 889 rc = vnic_modify_addr(pThis->u.s.VNICLinkId, &AddrType, &MacLen, MacAddr, &MacSlot, 0 /* Mac-Prefix Length */, &Result); 890 if (!rc) 891 { 892 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface vnic_modify successful %s mac %.*Rhxs\n", pThis->szName, 893 sizeof(GuestMac), &GuestMac)); 894 895 mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast); 896 pThis->u.s.hUnicast = NULL; 897 rc = mac_unicast_add(pThis->u.s.hClient, NULL /* MAC Address */, 898 MAC_UNICAST_PRIMARY | MAC_UNICAST_STRIP_DISABLE | 899 MAC_UNICAST_DISABLE_TX_VID_CHECK | MAC_UNICAST_NODUPCHECK | MAC_UNICAST_HW, 900 &pThis->u.s.hUnicast, 0 /* VLAN id */, &MacDiag); 901 902 if (!rc) 903 return VINF_SUCCESS; 904 905 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to set client MAC address (2) '%s' rc=%d\n", 906 pThis->szName, rc)); 907 } 908 else 909 { 910 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to modify MAC address for VNIC over '%s' rc=%d\n", 911 pThis->szName, rc)); 912 } 913 } 914 else 915 { 916 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to obtain VNIC link id for '%s' rc=%d\n", 917 pThis->szName, rc)); 918 } 919 } 920 else 921 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to set client MAC address over link '%s' rc=%d\n", 922 pThis->szName, rc)); 923 924 mac_client_close(pThis->u.s.hClient, 0 /* fFlags */); 925 pThis->u.s.hClient = NULL; 916 pThis->u.s.uInstance++; 917 LogFlow((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC successfully created VNIC '%s' over '%s'\n", pVNIC->szName, pThis->szName)); 918 *ppVNIC = pVNIC; 919 return VINF_SUCCESS; 926 920 } 927 921 else 928 { 929 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to create client over link '%s' rc=%d\n", 922 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC vboxNetFltSolarisInitVNIC failed. rc=%d\n", rc)); 923 924 mac_close(pVNIC->hInterface); 925 pVNIC->hInterface = NULL; 926 } 927 else 928 { 929 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to open VNIC '%s' over '%s'. rc=%d\n", pVNIC->szName, 930 930 pThis->szName, rc)); 931 } 932 } 933 else 934 { 935 LogFlow((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface VNIC creation failed over '%s'\n", pThis->szName)); 936 rc = ENXIO; 937 } 938 939 if (pThis->u.s.hInterface) 940 { 941 mac_close(pThis->u.s.hInterface); 942 pThis->u.s.hInterface = NULL; 943 } 944 945 vboxNetFltSolarisDestroyVNIC(pThis); 931 } 932 933 vboxNetFltSolarisDestroyVNIC(pVNIC); 934 rc = VERR_INTNET_FLT_IF_FAILED; 946 935 } 947 936 else 948 LogRel((DEVICE_NAME ":vboxNetFltSolarisAttachToInterface failed to open link '%s' rc=%d\n", pThis->szName, rc)); 937 { 938 LogRel((DEVICE_NAME ":vboxNetFltSolarisCreateVNIC failed to create VNIC '%s' over '%s' rc=%d Diag=%d\n", pVNIC->szName, 939 pThis->szName, rc, Diag)); 940 } 941 942 vboxNetFltSolarisFreeVNIC(pVNIC); 949 943 950 944 return RTErrConvertFromErrno(rc); 951 #endif952 }953 954 955 956 /**957 * Detach from the network interface.958 *959 * @param pThis The VM connection instance.960 * @returns corresponding VBox error code.961 */962 LOCAL int vboxNetFltSolarisDetachFromInterface(PVBOXNETFLTINS pThis)963 {964 #if 0965 AssertPtrReturn(pThis, VERR_INVALID_POINTER);966 967 if (pThis->u.s.hPromiscuous)968 {969 mac_promisc_remove(pThis->u.s.hPromiscuous);970 pThis->u.s.hPromiscuous = NULL;971 }972 973 if (pThis->u.s.hClient)974 {975 if (pThis->u.s.hUnicast)976 {977 mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast);978 pThis->u.s.hUnicast = NULL;979 }980 981 mac_rx_clear(pThis->u.s.hClient);982 983 mac_client_close(pThis->u.s.hClient, 0 /* fFlags */);984 pThis->u.s.hClient = NULL;985 }986 987 if (pThis->u.s.hInterface)988 {989 mac_close(pThis->u.s.hInterface);990 pThis->u.s.hInterface = NULL;991 }992 993 vboxNetFltSolarisDestroyVNIC(pThis);994 #endif995 945 } 996 946 … … 1034 984 { 1035 985 LogFlow((DEVICE_NAME ":vboxNetFltOsDisconnectIt pThis=%p\n", pThis)); 1036 // return vboxNetFltSolarisDetachFromInterface(pThis);1037 986 return VINF_SUCCESS; 1038 987 } … … 1042 991 { 1043 992 LogFlow((DEVICE_NAME ":vboxNetFltOsConnectIt pThis=%p\n", pThis)); 1044 // return vboxNetFltSolarisAttachToInterface(pThis, false /* fRediscovery */);1045 993 return VINF_SUCCESS; 1046 994 } … … 1052 1000 1053 1001 /* 1054 * If this is a VNIC remove the callbacks and close it. 1055 */ 1056 if (pThis->u.s.fIsVNIC) 1057 { 1058 if (pThis->u.s.hPromiscuous) 1059 { 1060 mac_promisc_remove(pThis->u.s.hPromiscuous); 1061 pThis->u.s.hPromiscuous = NULL; 1062 } 1063 1064 if (pThis->u.s.hClient) 1065 { 1066 if (pThis->u.s.hUnicast) 1067 { 1068 mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast); 1069 pThis->u.s.hUnicast = NULL; 1070 } 1071 1072 mac_rx_clear(pThis->u.s.hClient); 1073 1074 mac_client_close(pThis->u.s.hClient, 0 /* fFlags */); 1075 pThis->u.s.hClient = NULL; 1076 } 1077 1078 if (pThis->u.s.hInterface) 1079 { 1080 mac_close(pThis->u.s.hInterface); 1081 pThis->u.s.hInterface = NULL; 1082 } 1083 } 1084 1085 /** @todo clean-up for physical interfaces */ 1002 * Destroy all managed VNICs. If a VNIC was passed to us, there 1003 * will be only 1 item in the list, otherwise as many interfaces 1004 * that were somehow not destroyed using DisconnectInterface() will be 1005 * present. 1006 */ 1007 PVBOXNETFLTVNIC pVNIC = NULL; 1008 while ((pVNIC = list_remove_head(&pThis->u.s.hVNICs)) != NULL) 1009 { 1010 vboxNetFltSolarisDestroyVNIC(pVNIC); 1011 vboxNetFltSolarisFreeVNIC(pVNIC); 1012 } 1013 1014 list_destroy(&pThis->u.s.hVNICs); 1086 1015 } 1087 1016 … … 1094 1023 * Figure out if the interface is a VNIC or a physical/etherstub/whatever NIC. 1095 1024 */ 1096 int rc = mac_open_by_linkname(pThis->szName, &pThis->u.s.hInterface); 1025 mac_handle_t hInterface; 1026 int rc = mac_open_by_linkname(pThis->szName, &hInterface); 1097 1027 if (RT_LIKELY(!rc)) 1098 1028 { 1099 /* 1100 * Check if this is a VNIC. If it's not we will create a VNIC per guest interface 1101 * later (see vboxNetFltPortOsConnectInterface). 1102 */ 1103 rc = mac_is_vnic(pThis->u.s.hInterface); 1029 rc = mac_is_vnic(hInterface); 1104 1030 if (!rc) 1105 1031 { 1106 mac_close(pThis->u.s.hInterface); 1107 pThis->u.s.hInterface = NULL; 1032 /* 1033 * This is NOT a VNIC. Just pretend success for now. 1034 * We will create a VNIC per guest interface later (see vboxNetFltPortOsConnectInterface). 1035 */ 1108 1036 pThis->u.s.fIsVNIC = false; 1037 mac_unicast_primary_get(hInterface, pThis->u.s.MacAddr.au8); 1038 vboxNetFltSolarisReportInfo(pThis); 1039 mac_close(hInterface); 1109 1040 return VINF_SUCCESS; 1110 1041 } 1111 1042 1112 /*1113 * User has passed in a VNIC, we can proceed to open it.1114 * Open a client connection to the lower MAC interface.1115 */1116 1043 pThis->u.s.fIsVNIC = true; 1117 rc = mac_client_open(pThis->u.s.hInterface, &pThis->u.s.hClient, 1118 NULL, /* name of this client */1119 MAC_OPEN_FLAGS_USE_DATALINK_NAME | /* client name same as underlying NIC */1120 MAC_OPEN_FLAGS_MULTI_PRIMARY /* allow multiple primary unicasts */1121 );1122 if (RT_LIKELY(!rc))1123 { 1044 1045 PVBOXNETFLTVNIC pVNIC = vboxNetFltSolarisAllocVNIC(); 1046 if (RT_LIKELY(pVNIC)) 1047 { 1048 pVNIC->fCreated = false; 1049 pVNIC->hInterface = hInterface; 1050 1124 1051 /* 1125 1052 * Obtain the data link ID for this VNIC, it's needed for modifying the MAC address among other things. 1126 1053 */ 1127 rc = dls_mgmt_get_linkid(pThis->szName, &p This->u.s.hLinkId);1054 rc = dls_mgmt_get_linkid(pThis->szName, &pVNIC->hLinkId); 1128 1055 if (RT_LIKELY(!rc)) 1129 1056 { 1130 1057 /* 1131 * Set the RX callback.1058 * Initialize the VNIC and add it to the list of managed VNICs. 1132 1059 */ 1133 mac_diag_t Diag = MAC_DIAG_NONE; 1134 rc = mac_unicast_add_set_rx(pThis->u.s.hClient, 1135 NULL /* MAC address, use existing VNIC address */, 1136 MAC_UNICAST_PRIMARY | /* Use Primary address of the VNIC */ 1137 MAC_UNICAST_NODUPCHECK, /* Don't fail for conflicting MAC/VLAN-id combinations */ 1138 &pThis->u.s.hUnicast, 1139 0 /* VLAN-id */, 1140 &Diag, 1141 vboxNetFltSolarisRecv, /* RX callback */ 1142 pThis /* callback private data */ 1143 ); 1144 if (RT_LIKELY(!rc)) 1060 RTStrPrintf(pVNIC->szName, sizeof(pVNIC->szName), "%s", pThis->szName); 1061 rc = vboxNetFltSolarisInitVNIC(pThis, pVNIC); 1062 if (!rc) 1145 1063 { 1146 /* 1147 * Get the MAC handle of the underlying physical interface (or etherstub whatever). 1148 */ 1149 mac_handle_t hLowerMac = mac_get_lower_mac_handle(pThis->u.s.hInterface); 1150 if (RT_LIKELY(hLowerMac)) 1151 { 1152 /* 1153 * Obtain the MAC address & report. 1154 */ 1155 mac_unicast_primary_get(hLowerMac, (uint8_t *)&pThis->u.s.MacAddr.au8); 1156 if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) 1157 { 1158 Assert(pThis->pSwitchPort); 1159 pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); 1160 pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, false); /** @todo Promisc */ 1161 pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); 1162 pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); 1163 vboxNetFltRelease(pThis, true /*fBusy*/); 1164 } 1165 1166 LogFlow((DEVICE_NAME ":vboxNetFltOsInitInstance successfully opened VNIC '%s'\n", pThis->szName)); 1167 return VINF_SUCCESS; 1168 } 1169 else 1170 { 1171 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to get lower MAC handle for '%s'\n", pThis->szName)); 1172 rc = ENODEV; 1173 } 1174 1175 mac_unicast_remove(pThis->u.s.hClient, pThis->u.s.hUnicast); 1176 mac_rx_clear(pThis->u.s.hClient); 1177 pThis->u.s.hUnicast = NULL; 1064 list_insert_head(&pThis->u.s.hVNICs, pVNIC); 1065 return VINF_SUCCESS; 1178 1066 } 1179 1067 else 1180 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to set RX callback. rc=%d Diag=%d\n", rc, Diag));1068 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance vboxNetFltSolarisInitVNIC failed. rc=%d\n", rc)); 1181 1069 } 1182 1070 else 1183 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to open link id for '%s' rc=%d\n", pThis->szName, rc)); 1184 1185 mac_client_close(pThis->u.s.hClient, 0 /* flags */); 1186 pThis->u.s.hClient = NULL; 1071 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to get link id for '%s'. rc=%d\n", pThis->szName, rc)); 1072 1073 vboxNetFltSolarisFreeVNIC(pVNIC); 1187 1074 } 1188 1075 else 1189 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to open mac client for '%s' rc=%d\n", pThis->szName, rc)); 1076 LogRel((DEVICE_NAME ":vboxNetFltOsInitInstance failed to allocate VNIC private data.\n")); 1077 1078 mac_close(hInterface); 1190 1079 } 1191 1080 else … … 1202 1091 */ 1203 1092 pThis->u.s.fIsVNIC = false; 1093 list_create(&pThis->u.s.hVNICs, sizeof(VBOXNETFLTVNIC), offsetof(VBOXNETFLTVNIC, hNode)); 1204 1094 pThis->u.s.uInstance = 0; 1205 pThis->u.s.hInterface = NULL; 1206 pThis->u.s.hLinkId = DATALINK_INVALID_LINKID; 1207 pThis->u.s.hClient = NULL; 1208 pThis->u.s.hUnicast = NULL; 1209 pThis->u.s.hPromiscuous = NULL; 1095 pThis->u.s.pvVNIC = NULL; 1210 1096 bzero(&pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); 1097 pThis->u.s.fReportedInfo = false; 1211 1098 return VINF_SUCCESS; 1212 1099 } … … 1225 1112 { 1226 1113 /* 1227 * Xmit the packet down the interface (tx)1228 */ 1229 int rc = VERR_INVALID_HANDLE;1230 if (RT_LIKELY(pThis->u.s.hClient))1231 {1232 mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst);1233 if (RT_LIKELY(pMsg)) 1234 {1235 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg)));1236 1237 mac_tx_cookie_t pXmitCookie = mac_tx(pThis->u.s.hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */);1238 if (RT_LIKELY(!pXmitCookie))1239 return VINF_SUCCESS;1240 1241 pMsg = NULL;1242 rc = VERR_NET_IO_ERROR; 1243 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit Xmit failed.\n"));1244 }1245 else1246 { 1247 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n"));1248 rc = VERR_NO_MEMORY;1249 }1114 * Validate parameters. 1115 */ 1116 PVBOXNETFLTVNIC pVNIC = pvIfData; 1117 AssertMsgReturn(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC, 1118 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC), 1119 VERR_INVALID_PARAMETER); 1120 1121 /* 1122 * Xmit the packet down the appropriate VNIC interface. 1123 */ 1124 int rc = VINF_SUCCESS; 1125 mblk_t *pMsg = vboxNetFltSolarisMBlkFromSG(pThis, pSG, fDst); 1126 if (RT_LIKELY(pMsg)) 1127 { 1128 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit pThis=%p cbData=%d\n", pThis, MBLKL(pMsg))); 1129 1130 mac_tx_cookie_t pXmitCookie = mac_tx(pVNIC->hClient, pMsg, 0 /* Hint */, MAC_DROP_ON_NO_DESC, NULL /* return message */); 1131 if (RT_LIKELY(!pXmitCookie)) 1132 return VINF_SUCCESS; 1133 1134 pMsg = NULL; 1135 rc = VERR_NET_IO_ERROR; 1136 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit Xmit failed pVNIC=%p.\n", pVNIC)); 1250 1137 } 1251 1138 else 1252 LogFlow((DEVICE_NAME ":vboxNetFltPortOsXmit missing client.\n")); 1139 { 1140 LogRel((DEVICE_NAME ":vboxNetFltPortOsXmit no memory for allocating Xmit packet.\n")); 1141 rc = VERR_NO_MEMORY; 1142 } 1253 1143 1254 1144 return rc; … … 1258 1148 void vboxNetFltPortOsNotifyMacAddress(PVBOXNETFLTINS pThis, void *pvIfData, PCRTMAC pMac) 1259 1149 { 1260 LogRel((DEVICE_NAME ":vboxNetFltPortOSNotifyMacAddress %s %.6Rhxs\n", pThis->szName, pMac)); 1261 1150 LogFlow((DEVICE_NAME ":vboxNetFltPortOSNotifyMacAddress %s %.6Rhxs\n", pThis->szName, pMac)); 1151 1152 /* 1153 * Validate parameters. 1154 */ 1155 PVBOXNETFLTVNIC pVNIC = pvIfData; 1156 AssertMsgReturnVoid(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC, 1157 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC)); 1158 AssertMsgReturnVoid(pVNIC->hLinkId != DATALINK_INVALID_LINKID, 1159 ("Invalid hLinkId pVNIC=%p magic=%#x\n", pVNIC, pVNIC->u32Magic)); 1160 1161 /* 1162 * Set the MAC address of the VNIC to the one used by the VM interface. 1163 */ 1262 1164 uchar_t au8GuestMac[MAXMACADDRLEN]; 1263 1165 bcopy(pMac->au8, au8GuestMac, sizeof(RTMAC)); 1264 1166 1265 if (pThis->u.s.fIsVNIC) 1266 { 1267 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED; 1268 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE; 1269 int MacSlot = 0; 1270 int MacLen = sizeof(RTMAC); 1271 1272 int rc = vnic_modify_addr(pThis->u.s.hLinkId, &AddrType, &MacLen, au8GuestMac, &MacSlot, 0 /* Mac-Prefix Length */, &Diag); 1273 if (!rc) 1274 LogFlow((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress set '%s' MAC address to %.6Rhxs\n", pThis->szName, pMac)); 1167 vnic_mac_addr_type_t AddrType = VNIC_MAC_ADDR_TYPE_FIXED; 1168 vnic_ioc_diag_t Diag = VNIC_IOC_DIAG_NONE; 1169 int MacSlot = 0; 1170 int MacLen = sizeof(RTMAC); 1171 1172 int rc = vnic_modify_addr(pVNIC->hLinkId, &AddrType, &MacLen, au8GuestMac, &MacSlot, 0 /* Mac-Prefix Length */, &Diag); 1173 if (RT_UNLIKELY(rc)) 1174 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed! rc=%d Diag=%d\n", rc, Diag)); 1175 } 1176 1177 1178 int vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **ppvIfData) 1179 { 1180 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface pThis=%p pvIf=%p\n", pThis, pvIf)); 1181 1182 int rc = VINF_SUCCESS; 1183 1184 /* 1185 * If the underlying interface is not a VNIC, we need to create 1186 * a VNIC per guest NIC. 1187 */ 1188 if (!pThis->u.s.fIsVNIC) 1189 { 1190 PVBOXNETFLTVNIC pVNIC = NULL; 1191 rc = vboxNetFltSolarisCreateVNIC(pThis, &pVNIC); 1192 if (RT_SUCCESS(rc)) 1193 { 1194 /* 1195 * VM Interface<->VNIC association so that we can Xmit/Recv on the right ones. 1196 */ 1197 pVNIC->pvIf = pvIf; 1198 *ppvIfData = pVNIC; 1199 1200 /* 1201 * Add the created VNIC to the list of VNICs we manage. 1202 */ 1203 list_insert_tail(&pThis->u.s.hVNICs, pVNIC); 1204 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface successfully created VNIC '%s'.\n", pVNIC->szName)); 1205 return VINF_SUCCESS; 1206 } 1275 1207 else 1276 LogRel((DEVICE_NAME ":vboxNetFltPortOsNotifyMacAddress failed! rc=%d Diag=%d\n", rc, Diag)); 1277 } 1278 1279 /** @todo set MAC address for created VNICs */ 1280 } 1281 1282 1283 int vboxNetFltPortOsConnectInterface(PVBOXNETFLTINS pThis, void *pvIf, void **pvIfData) 1284 { 1285 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface\n")); 1208 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface failed to create VNIC\n")); 1209 } 1210 else 1211 { 1212 PVBOXNETFLTVNIC pVNIC = list_head(&pThis->u.s.hVNICs); 1213 if (RT_LIKELY(pVNIC)) 1214 { 1215 *ppvIfData = pVNIC; 1216 LogFlow((DEVICE_NAME ":vboxNetFltPortOsConnectInterface set VNIC '%s' private data\n", pVNIC->szName)); 1217 } 1218 else 1219 { 1220 LogRel((DEVICE_NAME ":vboxNetFltPortOsConnectInterface huh!? Missing VNIC!\n")); 1221 return VERR_GENERAL_FAILURE; 1222 } 1223 } 1224 1225 return rc; 1226 } 1227 1228 1229 int vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData) 1230 { 1231 LogFlow((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface pThis=%p\n", pThis)); 1232 1233 PVBOXNETFLTVNIC pVNIC = pvIfData; 1234 AssertMsgReturn(VALID_PTR(pVNIC) && pVNIC->u32Magic == VBOXNETFLTVNIC_MAGIC, 1235 ("Invalid pvIfData=%p magic=%#x (expected %#x)\n", pvIfData, pVNIC ? pVNIC->u32Magic : 0, VBOXNETFLTVNIC_MAGIC), 1236 VERR_INVALID_POINTER); 1237 1238 /* 1239 * If the underlying interface is not a VNIC, we need to delete the created VNIC. 1240 */ 1241 if (!pThis->u.s.fIsVNIC) 1242 { 1243 /* 1244 * Remove the VNIC from the list, destroy and free it. 1245 */ 1246 list_remove(&pThis->u.s.hVNICs, pVNIC); 1247 LogRel((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface destroying pVNIC=%p\n", pVNIC)); 1248 vboxNetFltSolarisDestroyVNIC(pVNIC); 1249 vboxNetFltSolarisFreeVNIC(pVNIC); 1250 } 1251 1286 1252 return VINF_SUCCESS; 1287 1253 } 1288 1254 1289 1290 int vboxNetFltPortOsDisconnectInterface(PVBOXNETFLTINS pThis, void *pvIfData)1291 {1292 LogRel((DEVICE_NAME ":vboxNetFltPortOsDisconnectInterface\n"));1293 return VINF_SUCCESS;1294 }1295
Note:
See TracChangeset
for help on using the changeset viewer.