Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 12 Next »

The next API function is the AddrMulticastAdd() function used to configure a device with an (IP-to-Ethernet) multicast hardware address.

Files

Every device driver’s net_dev.c

Prototype

          static void NetDev_AddrMulticastAdd (NET_IF     *p_if,
                                               CPU_INT08U *p_addr_hw,
                                               CPU_INT08U  addr_hw_len,
                                               NET_ERR    *p_err);


Note that since every device driver’s AddrMulticastAdd() function is accessed only by function pointer via the device driver’s API structure, it doesn’t need to be globally available and should therefore be declared as ‘static’.

Arguments

p_if

Pointer to the interface to add/configure a multicast address.

p_addr_hw

Pointer to multicast hardware address to add.

addr_hw_len

Length of multicast hardware address.

p_err

Pointer to variable that will receive the return error code from this function.

Returned Value

None.

Required Configuration

Necessary only if NET_IP_CFG_MULTICAST_SEL is configured for transmit and receive multicasting (see NET_IP_CFG_MULTICAST_SEL).

Notes / Warnings

Since many network controllers’ documentation fail to properly indicate how to add/configure an MAC device with a multicast address, the following methodology is recommended for determining and testing the correct multicast hash bit algorithm.

  1. Configure a packet capture program or multicast application to broadcast a multicast packet with destination address of 01:00:5E:00:00:01. This MAC address corresponds to the multicast group IP address of 224.0.0.1 which will be converted to a MAC address by higher layers and passed to this function.
  2. Set a break point in the receive ISR handler and transmit one send packet to the target. The break point should not be reached as the result of the transmitted packet. Use caution to ensure that other network traffic is not the source of the interrupt when the button is pressed. Sometimes asynchronous network events happen very close in time and the end result can be deceiving. Ideally, these tests should be performed on an isolated network but disconnect as many other hosts from the network as possible.
  3. Use the debugger to stop the application and program the MAC multicast hash register low bits to 0xFFFFFFFF. Go to step 2. Repeat for the hash bit high register if necessary. The goal is to bracket off which bit in either the high or low hash bit register causes the device to be interrupted when the broadcast frame is received by the target. Once the correct bit is known, the hash algorithm can be easily written and tested.
  4. The following hash bit algorithm code below could be adjusted per the network controller’s documentation in order to get the hash from the correct subset of CRC bits. Most of the code is similar between various devices and is thus reusable. The hash algorithm is the exclusive OR of every 6th bit of the destination address:

    hash[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
    hash[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
    hash[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
    hash[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
    hash[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
    hash[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]

    Where da0 represents the least significant bit of the first byte of the destination address received and where da47 represents the most significant bit of the last byte of the destination address received.




                                                                /* ---------- CALCULATE HASH CODE ---------- */
              hash = 0;
              for (i = 0; i < 6; i++) {                         /* For each row in the bit hash table:       */
                  bit_val = 0;                                  /* Clear initial xor value for each row.     */
                  for (j = 0; j < 8; j++) {                     /* For each bit in each octet:               */
                      bit_nbr    = (j * 6) + i;                 /* Determine which bit in stream, 0-47.      */
                      octet_nbr  =  bit_nbr / 8;                /* Determine which octet bit belongs to.     */
                      octet      =  paddr_hw[octet_nbr];        /* Get octet value.                          */
                      bit        =  octet & (1 << (bit_nbr % 8));  /* Check if octet's bit is set.           */
                      bit_val   ^= (bit > 0) ? 1 : 0;           /* Calculate table row's XOR hash value.     */
                  }
                   hash |= (bit_val << i);                      /* Add row's XOR hash value to final hash.   */
              }
                                                                /* ---- ADD MULTICAST ADDRESS TO DEVICE ---- */
              reg_sel = (hash >> 5) & 0x01;                     /* Determine hash register     to configure. */
              reg_bit = (hash >> 0) & 0x1F;                     /* Determine hash register bit to configure. */
                                                                /* (Substitute '0x01'/'0x1F' with device's ..*/
                                                                /* .. actual hash register bit masks/shifts.)*/
               
                paddr_hash_ctrs = &pdev_data->MulticastAddrHashBitCtr[hash];
              (*paddr_hash_ctrs)++;                             /* Increment hash bit reference counter.     */
               
              if (reg_sel == 0) {                               /* Set multicast hash register bit.          */
                  pdev->MCAST_REG_LO |= (1 << reg_bit);         /* (Substitute 'MCAST_REG_LO/HI' with ..     */
              } else {                                          /* .. device's actual multicast registers.)  */
                  pdev->MCAST_REG_HI |= (1 << reg_bit);
              }
                                                                /* ---------- CALCULATE HASH CODE ---------- */
                                                                /* Calculate CRC.                            */
              crc = NetUtil_32BitCRC_Calc((CPU_INT08U *)paddr_hw,
                                          (CPU_INT32U  )addr_hw_len,
                                          (NET_ERR    *)perr);


    Alternatively, you may be able to compute the CRC hash with a call to
    NetUtil_32BitCRC_CalcCpl() followed by an optional call to NetUtil_32BitReflect() , with four possible combinations:

    a. CRC without complement and without reflection

    b. CRC without complement and with reflection

    c. CRC with complement and without reflection

    d. CRC with complement and with reflection

              if (*perr != NET_UTIL_ERR_NONE) {
                   return;
              }
                                                                /* ---- ADD MULTICAST ADDRESS TO DEVICE ---- */
              crc     =  NetUtil_32BitReflect(crc);             /* Optionally, complement CRC.               */
              hash    = (crc >> 23u) & 0x3F;                    /* Determine hash register     to configure. */
              reg_bit = (hash % 32u);                           /* Determine hash register bit to configure. */
                                                                /* (Substitute '23u'/'0x3F' with device's .. */
                                                                /* .. actual hash register bit masks/shifts.)*/
               
                paddr_hash_ctrs = &pdev_data->MulticastAddrHashBitCtr[hash];
              (*paddr_hash_ctrs)++;                             /* Increment hash bit reference counter.     */
               
              if (hash <= 31u) {                                /* Set multicast hash register bit.          */
                  pdev->MCAST_REG_LO |= (1 << reg_bit);         /* (Substitute 'MCAST_REG_LO/HI' with ..     */
              } else {                                          /* .. device's actual multicast registers.)  */
                  pdev->MCAST_REG_HI |= (1 << reg_bit);
              }
    
    

    Unfortunately, the product documentation will not likely tell you which combination of complement and reflection is necessary in order to properly compute the hash value. Most likely, the documentation will simply state ‘Standard Ethernet CRC’ which when compared to other documents, means any of the four combinations above; different than the actual frame CRC.

    Fortunately, if the code is written to perform both the complement and reflection, then the debugger may be used to repeat the code block over and over skipping either the line that performs the complement or the function call to the reflection until the output hash bit is computed correctly.

  5. Update the device driver’s AddrMulticastAdd() function to calculate and configure the correct CRC.
  6. Test the device driver’s AddrMulticastAdd() function by ensuring that the group address 224.0.0.1, when joined from the application (see section C-11-1), correctly configures the device to receive multicast packets destined to the 224.0.0.1 address. Then broadcast the 224.0.0.1 (see step 1) to test if the device receives the multicast packet.
  • No labels