third_party/virtualbox/src/VBox/Devices/Network/DevE1000.cpp
/**
 * Determines if the packet is to be delivered to upper layer.
 *
 * The following filters supported:
 * - Exact Unicast/Multicast
 * - Promiscuous Unicast/Multicast
 * - Multicast
 * - VLAN
 *
 * @returns true if packet is intended for this node.
 * @param   pThis          Pointer to the state structure.
 * @param   pvBuf           The ethernet packet.
 * @param   cb              Number of bytes available in the packet.
 * @param   pStatus         Bit field to store status bits.
 * @thread  EMT
 */
Determines if the packet is to be delivered to upper layer.
The following filters supported:
- Exact Unicast/Multicast
- Promiscuous Unicast/Multicast
- Multicast
- VLAN

@returns true if packet is intended for this node.
@param   pThis          Pointer to the state structure.
@param   pvBuf           The ethernet packet.
@param   cb              Number of bytes available in the packet.
@param   pStatus         Bit field to store status bits.
@thread  EMT
Determines if the packet is to be delivered to upper layer . The following filters supported : - Exact Unicast / Multicast - Promiscuous Unicast / Multicast - Multicast - VLAN @returns true if packet is intended for this node . @param pThis Pointer to the state structure . @param pvBuf The ethernet packet . @param cb Number of bytes available in the packet . @param pStatus Bit field to store status bits . @thread EMT
static bool e1kAddressFilter(PE1KSTATE pThis, const void *pvBuf, size_t cb, E1KRXDST *pStatus)
{
    Assert(cb > 14);
    pStatus->fPIF = false;
    pStatus->fVP  = false;
    if (cb > E1K_MAX_RX_PKT_SIZE)
    {
        E1kLog(("%s ERROR: Incoming packet is too big, cb=%d > max=%d\n",
                pThis->szPrf, cb, E1K_MAX_RX_PKT_SIZE));
        E1K_INC_CNT32(ROC);
        return false;
    }
    else if (!(RCTL & RCTL_LPE) && cb > 1522)
    {
        E1kLog(("%s Discarding incoming packet (LPE=0), cb=%d\n",
                pThis->szPrf, cb));
        E1K_INC_CNT32(ROC);
        return false;
    }
    uint16_t *u16Ptr = (uint16_t*)pvBuf;
    if (RT_BE2H_U16(u16Ptr[6]) == VET)
    {
        pStatus->fVP = true;
        if (RCTL & RCTL_VFE)
        {
            if (RCTL & RCTL_CFIEN)
            {
                E1kLog3(("%s VLAN filter: VLAN=%d CFI=%d RCTL_CFI=%d\n", pThis->szPrf,
                         E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7])),
                         E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])),
                         !!(RCTL & RCTL_CFI)));
                if (E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])) != !!(RCTL & RCTL_CFI))
                {
                    E1kLog2(("%s Packet filter: CFIs do not match in packet and RCTL (%d!=%d)\n",
                             pThis->szPrf, E1K_SPEC_CFI(RT_BE2H_U16(u16Ptr[7])), !!(RCTL & RCTL_CFI)));
                    return false;
                }
            }
            else
                E1kLog3(("%s VLAN filter: VLAN=%d\n", pThis->szPrf,
                         E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))));
            if (!ASMBitTest(pThis->auVFTA, E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))))
            {
                E1kLog2(("%s Packet filter: no VLAN match (id=%d)\n",
                         pThis->szPrf, E1K_SPEC_VLAN(RT_BE2H_U16(u16Ptr[7]))));
                return false;
            }
        }
    }
    if (e1kIsBroadcast(pvBuf) && (RCTL & RCTL_BAM))
        return true;
    E1kLog2(("%s Packet filter: not a broadcast\n", pThis->szPrf));
    if (e1kIsMulticast(pvBuf))
    {
        if (RCTL & RCTL_MPE)
            return true;
        E1kLog2(("%s Packet filter: no promiscuous multicast\n", pThis->szPrf));
        if (e1kPerfectMatch(pThis, pvBuf))
        {
            pStatus->fPIF = true;
            return true;
        }
        E1kLog2(("%s Packet filter: no perfect match\n", pThis->szPrf));
        if (e1kImperfectMatch(pThis, pvBuf))
            return true;
        E1kLog2(("%s Packet filter: no imperfect match\n", pThis->szPrf));
    }
    else {
        if (RCTL & RCTL_UPE)
            return true;
        E1kLog2(("%s Packet filter: no promiscuous unicast\n", pThis->szPrf));
        if (e1kPerfectMatch(pThis, pvBuf))
        {
            pStatus->fPIF = true;
            return true;
        }
        E1kLog2(("%s Packet filter: no perfect match\n", pThis->szPrf));
    }
    E1kLog2(("%s Packet filter: packet discarded\n", pThis->szPrf));
    return false;
}
static bool e1kAddressFilter ( PE1KSTATE pThis , const void * pvBuf , size_t cb , E1KRXDST * pStatus ) { Assert ( cb > 14 ) ; pStatus -> fPIF = false ; pStatus -> fVP = false ; if ( cb > E1K_MAX_RX_PKT_SIZE ) { E1kLog ( ( " \n " , pThis -> szPrf , cb , E1K_MAX_RX_PKT_SIZE ) ) ; E1K_INC_CNT32 ( ROC ) ; return false ; } else if ( ! ( RCTL & RCTL_LPE ) && cb > 1522 ) { E1kLog ( ( " \n " , pThis -> szPrf , cb ) ) ; E1K_INC_CNT32 ( ROC ) ; return false ; } uint16_t * u16Ptr = ( uint16_t * ) pvBuf ; if ( RT_BE2H_U16 ( u16Ptr [ 6 ] ) == VET ) { pStatus -> fVP = true ; if ( RCTL & RCTL_VFE ) { if ( RCTL & RCTL_CFIEN ) { E1kLog3 ( ( " \n " , pThis -> szPrf , E1K_SPEC_VLAN ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) , E1K_SPEC_CFI ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) , ! ! ( RCTL & RCTL_CFI ) ) ) ; if ( E1K_SPEC_CFI ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) != ! ! ( RCTL & RCTL_CFI ) ) { E1kLog2 ( ( " \n " , pThis -> szPrf , E1K_SPEC_CFI ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) , ! ! ( RCTL & RCTL_CFI ) ) ) ; return false ; } } else E1kLog3 ( ( " \n " , pThis -> szPrf , E1K_SPEC_VLAN ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) ) ) ; if ( ! ASMBitTest ( pThis -> auVFTA , E1K_SPEC_VLAN ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) ) ) { E1kLog2 ( ( " \n " , pThis -> szPrf , E1K_SPEC_VLAN ( RT_BE2H_U16 ( u16Ptr [ 7 ] ) ) ) ) ; return false ; } } } if ( e1kIsBroadcast ( pvBuf ) && ( RCTL & RCTL_BAM ) ) return true ; E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; if ( e1kIsMulticast ( pvBuf ) ) { if ( RCTL & RCTL_MPE ) return true ; E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; if ( e1kPerfectMatch ( pThis , pvBuf ) ) { pStatus -> fPIF = true ; return true ; } E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; if ( e1kImperfectMatch ( pThis , pvBuf ) ) return true ; E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; } else { if ( RCTL & RCTL_UPE ) return true ; E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; if ( e1kPerfectMatch ( pThis , pvBuf ) ) { pStatus -> fPIF = true ; return true ; } E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; } E1kLog2 ( ( " \n " , pThis -> szPrf ) ) ; return false ; }
Determines if the packet is to be delivered to upper layer.
Determines if the packet is to be delivered to upper layer .
/* Assume that we fail to pass exact filter. */ /* Discard oversized packets */ /* When long packet reception is disabled packets over 1522 are discarded */ /* Compare TPID with VLAN Ether Type */ /* Is VLAN filtering enabled? */ /* It is 802.1q packet indeed, let's filter by VID */ /* Broadcast filtering */ /* Is multicast promiscuous enabled? */ /* Try perfect matches first */ /* Is unicast promiscuous enabled? */