Subject: PSARC FastTrack [04/28/2006]: Multiple MAC address support Template Version: @(#)sac_nextcase 1.56 10/26/05 SMI 1. Introduction 1.1. Project/Component Working Name: Multiple MAC address support 1.2. Name of Document Author/Supplier: Author: Rajagopal Kunhappan 1.3 Date of This Document: 21 April, 2006 4. Technical Description Multiple MAC address support ============================ release binding:patch 1 Introduction ============== There are NICs available like bge, e1000g, etc that are capable of supporting multiple MAC addresses. This proposal provides a mechanism by which mac clients can query the underlying NIC to see if it supports multiple MAC addresses and provides a way to use this feature. The feature is needed by the LDoms project (Bug 6339368: Ability to set multiple MAC addresses to a network interface) and will be used by Crossbow (which has not yet ARC'd). The proposal treats multiple MAC addresses on a NIC like any other resource, for eg. Rx/Tx rings. An entity that wants to use it should first see if it is available, reserve it and use it, and then release it. This would mean a way to add and remove MAC addresses along with modify and get should be provided by the drivers. Drivers should advertise the support of this feature through a new capability (mac_capab_t type): MAC_CAPAB_MULTIADDRESS 2 Overview ========== Mac clients wanting to use MAC_CAPAB_MULTIADDRESS capability would first use mac_capab_get() to determine if the underlying NIC supports this capability. This call will return the total number of MAC addresses supported, free address slots available and whether factory MAC addresses are available or not. The call will also return the function entry points in the driver to add, reserve, modify, get and remove a unicast MAC address. Note: Address slots are used to identify the addresses. A call to reserve or add will return this as one of the values. This value is used as the handle by modify and remove routines to identify an address to modify or remove. Address slots can take values from 0 to (total addresses - 1). If a mac client wants to use the factory MAC address, it should use maddr_factory_reserve() call to reserve a factory address. maddr_factory_reserve() will return the address, the slot where the address is reserved and enable the NIC to start filtering on the MAC address. If mac client wants to provide its own address, it should use maddr_add() instead. It will add the MAC address, enable the NIC to start filtering on the MAC address and return the slot number where the address was added. The returned slot number should be saved for it needs to be passed in the calls to modify or remove the mac address. After the mac client is done using the mac address, it should be released with a call to maddr_remove(). Since the facility provides for new MAC addresses to be added and modified, the project proposes to add a new mac layer function, mac_unicst_verify() that mac clients should use to verify the address added/modified before calling the driver entry points. 3 MAC_CAPAB_MULTIADDRESS ======================== typedef enum { MAC_CAPAB_HCKSUM, MAC_CAPAB_POLL, /* new capabilities are defined here */ MAC_CAPAB_MULTIADDRESS } mac_capab_t; mac_capab_get() is used to query for this capability and to get other information related to the capability. 4 mac_capab_get() ================ boolean_t mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data); cap is MAC_CAPAB_MULTIADDRESS. cap_data is multiaddress_capab_t. typedef struct multiaddress_capab_s { int maddr_naddr; /* total addresses */ int maddr_naddrfree;/* free address slots */ /* driver entry points */ maddr_handle_t maddr_handle; /* cookie to be used for the calls */ maddr_factory_reserve_t maddr_factory_reserve; /* reserve a factory address */ maddr_add_t maddr_add; /* add a new unicst address */ maddr_remove_t maddr_remove; /* remove an added address */ maddr_modify_t maddr_modify; /* modify an added address */ maddr_get_t maddr_get; /* get address from specified slot */ } multiaddress_capab_t; Success (B_TRUE) would mean the capability is supported and cap_data will contain the toal number of MAC addresses supported (maddr_naddr) and the number of free address slots available (maddr_naddrfree) for setting new MAC addresses. Drivers supporting multiple mac addresses should provide entry points to add (maddr_add()), remove (maddr_remove()), modify (maddr_modify()) and to get (maddr_get) the addresses. Drivers that have multiple pre-defined factory MAC addresses should provide an entry point to reserve (madd_reserve()) a MAC address. If maddr_factory_reserve is non-NULL, it means factory defined multiple MAC addresses are available. Drivers should fill maddr_handle which the clients will use to access the driver entry points directly. 5 Driver entry points ===================== typedef int (*maddr_factory_reserve_t)(maddr_handle_t, mac_multi_addr_t *); typedef int (*maddr_add_t)(maddr_handle_t, mac_multi_addr_t *); typedef int (*maddr_remove_t)(maddr_handle_t, mac_addr_slot_t); typedef int (*maddr_modify_t)(maddr_handle_t, mac_multi_addr_t *); typedef int (*maddr_get_t)(maddr_handle_t, mac_multi_addr_t *); where maddr_handle_t, mac_addr_slot_t and mac_multi_addr_t are: typedef void * maddr_handle_t; typedef int mac_addr_slot_t; typedef struct mac_multi_address_s { mac_addr_slot_t mma_slot; /* slot for add/remove/get/set */ uint_t mma_addrlen; uint8_t mma_addr[MAXMACADDRLEN]; uint_t mma_flags; } mac_multi_addr_t; 5.1 maddr_factory_reserve ------------------------- typedef int (*maddr_factory_reserve)(maddr_handle_t, mac_multi_addr_t *); Some NICs come with multiple factory defined unicast addresses. In this case, the user would want to get a factory defined address. Such drivers should provide an entry point to reserve a factory defined MAC address. mac_multi_addr_t is passed in the call. All other NICs that do not have factory defined multiple MAC addresses will set this entry point to NULL. On success, the driver will fill mac_multi_addr_t with the slot number of the vendor address reserved, the reserved address and the address length. The driver will also enable the NIC to start filtering on the new reserved MAC address. The returned slot number should be saved as it needs to be passed in the call to modify or remove the address. On success, maddr_factory_reserve returns 0. If unable to reserve an address, ENOSPC is returned. To unreserve an address, maddr_remove() should be called passing the slot number that was returned by maddr_factory_reserve(). 5.2 maddr_add ------------- typedef int (*maddr_add_t)(maddr_handle_t, mac_multi_addr_t *); If multiple factory addresses are not present, or even if present but the user desires to add his own MAC address, maddr_add() entry point should be called passing the address in mac_multi_addr_t. mma_addrlen should be set to the size of the address passed. mma_flags should be set to 0. maddr_add() will find an unused address slot, set the address value to the one specified, reserve that slot and enable the NIC to start filtering on the new MAC address (along with other MAC addresses that it already is filtering on). On success, 0 is returned and mma_slot will indicate the slot to where it added the address. The returned slot number should be saved as it needs to be passed in the call to modify or remove the address. Otherwise it will return an error number indicating failure. The call can fail due to no slots available (ENOSPC), invalid address passed (EINVAL) or addrlen is invalid (EINVAL). 5.3 maddr_remove ---------------- typedef int (*maddr_remove_t)(maddr_handle_t, mac_addr_slot_t); maddr_remove() entry point should be called by the client to remove a MAC address that it added or reserved. The slot number that was returned in maddr_add() or maddr_factory_reserve() is passed in the call to remove the address. This will also cause the NIC to stop filtering on that MAC address. Returns 0 on success or EINVAL if a wrong slot is passed. 5.4 maddr_modify ---------------- typedef int (*maddr_modify_t)(maddr_handle_t, mac_multi_addr_t *); This is the routine that is used to modify the value of an address that has been added by maddr_add() or reserved by maddr_factory_reserve(). The new address, address length and the slot number that was returned in the call to add/reserve should be passed to maddr_modify(). mma_flags should be set to 0. Returns 0 on success. The request can fail with EINVAL if an invalid slot is passed. A slot is invalid if it is out of range or is not reserved or added by the client. 5.5 maddr_get ------------- typedef int (*maddr_get_t)(maddr_handle_t, mac_multi_addr_t *); Will get all the information related to the address slot passed in mac_multi_addr_t as well as the address. mma_flags should be set to 0 in the call. /* mma_flags values */ #define MMAC_SLOT_USED 0x1 /* address slot used */ #define MMAC_VENDOR_ADDR 0x2 /* address returned is vendor supplied */ On success, mma_flags can take the following values: 1) MMAC_SLOT_USED 2) MMAC_VENDOR_ADDR 3) MMAC_SLOT_USED | MMAC_VENDOR_ADDR 4) 0 (MMAC_SLOT_USED) indicates that the slot is being used and mma_addr contains the address. (MMAC_VENDOR_ADDR) indicates that mma_addr contains factory address and the address is unused. (MMAC_SLOT_USED|MMAC_VENDOR_ADDR) indicates that the slot is used and there is factory defined address for that slot and that address is returned in mma_addr. If none of the bits are set on return, it means that the slot is free and there is no address in the slot. maddr_get() return 0 on success and fails with EINVAL if the slot is invalid. 6 mac_unicst_verify =================== boolean_t mac_unicst_verify(mac_handle_t mh, const uint8_t *addr); mac_unicst_verify() will test if the passed address is a group address or not. It returns B_TRUE if address is not a group address. mac_unicst_verify() should be called by the clients before they pass the MAC address to the driver's add (maddr_add) or modify (maddr_modify) entry points. 7 Interface Table ================= _____________________________________________________________________________ | Interfaces Exported | |_______________________|_______________________|___________________________| |Interface | Classification | Comments | |_______________________|_______________________|___________________________| | | | | |MAC_CAPAB_MULTIADDRESS | Consolidation Private | | |mac_unicst_verify() | Consolidation Private | | |multiaddress_capab_t | Consolidation Private | | |mac_multi_addr_t | Consolidation Private | | |_______________________|_______________________|___________________________| 8 References: ============= PSARC/2006/248 Nemo MAC-Type Plugin Architecture PSARC/2006/249 Nemo Changes for Binary Compatibility 6. Resources and Schedule 6.4. Steering Committee requested information 6.4.1. Consolidation C-team Name: ON 6.5. ARC review type: FastTrack