Index: Pn_PPSM.c =================================================================== --- Pn_PPSM.c (revision 119172) +++ Pn_PPSM.c (working copy) @@ -27,36 +27,8 @@ } PN_PPSM_TRUTH_TABLE_RESULT_T; -/** - * @brief Check if neighbor at the given port is an end station. - * - * @param ptTLVChassisId Start of the LLDP TLV - * @return True if the neighbor is an end station, otherwise False. - */ -static bool Pn_PPSM_EndStationCheck(const LLDP_PDU_TLV_SYSTEM_CAPABILITIES_T *ptTLVSysCap) -{ - bool fRetval = false; - - if(NTOH16(ptTLVSysCap->usSystemCapabilites) & PN_PPSM_LLDP_ENDSTATION_BITMAP) - { - // end station capability supported = necessary condition - if(NTOH16(ptTLVSysCap->usEnabledCapabilites) & PN_PPSM_LLDP_ENDSTATION_BITMAP) - { - //end station capability marked as primary function = sufficient condition - fRetval = true; - } - } - return fRetval; -} - - -/** - * @brief Get peers name of station, if it exists. - * - * @param ptTLVChassisId Start point of LLDP TLV - * @return True if the name of station exists, otherwise False. - */ -static bool Pn_PPSM_GetNameOfStation(const LLDP_PDU_TLV_CHASSISID_T* ptTLVChassisId, +static bool +Pn_PPSM_GetNameOfStation(const LLDP_PDU_TLV_CHASSISID_T* ptTLVChassisId, const uint8_t** ppbNameOfStation, uint8_t* ptLenNameOfStation) { @@ -136,31 +108,7 @@ return bRetval; } - /** - * @brief Evaluating a dedicated truth table defined within the PN spec "chapter 4.12.7.6 - Truth and behavior tables" "Table 457 – PPSM truth table" - * - * @param hPeer LLDP peer - * @return PN_PPSM_TRUTH_TABLE_RESULT_OPTIMIZED when the peer is a end station, otherwise - * PN_PPSM_TRUTH_TABLE_RESULT_DEFAULT. - */ -static PN_PPSM_TRUTH_TABLE_RESULT_T Pn_PPSM_EvaluateTruthTable(const LLDP_PDU_TLV_CHASSISID_T *ptTLVChassisId, - const LLDP_PDU_TLV_SYSTEM_CAPABILITIES_T *ptTLVSysCap, - const uint8_t** ppbNameOfStation, - uint8_t* ptLenNameOfStation) -{ - PN_PPSM_TRUTH_TABLE_RESULT_T fRetval = PN_PPSM_TRUTH_TABLE_RESULT_DEFAULT; - - if((NULL != ptTLVChassisId) && (NULL != ptTLVSysCap)) - if(Pn_PPSM_EndStationCheck(ptTLVSysCap)) - if(Pn_PPSM_GetNameOfStation(ptTLVChassisId, ppbNameOfStation, ptLenNameOfStation)) - fRetval = PN_PPSM_TRUTH_TABLE_RESULT_OPTIMIZED; - return fRetval; -} - - -/** * @brief Iterate over the whole multicast address range (0x20 - 0x3f) and disable all dcp * multicast addresses but the newly calculated one. * This is done to be independent from the initial state of the switch. @@ -191,7 +139,8 @@ * @param ptPnCore Pointer to PROFINET Core structure * @param ptPrm Pointer to control parameter structure dedicated to the used ioctl command define */ -static void Pn_PPSM_DiasbleOtherPeerMcastAddrInRange(PN_CORE_RSC_T *ptPnCore, +static void +Pn_PPSM_DiasbleOtherPeerMcastAddrInRange(PN_CORE_RSC_T *ptPnCore, DRV_ETH_IOCTL_PRM_MCAST_FRWD_T *ptPrm) { ETH_MAC_ADDR_T tBaseMac = ETH_MAC_PN_DCP_IDENT; @@ -236,29 +185,106 @@ } } +static bool +Pn_Peer_isEndStation(LLDP_PEER_H hPeer) +{ + const LLDP_PDU_TLV_SYSTEM_CAPABILITIES_T *ptTLVSysCap = LLDP_FindTLV(LLDP_Peer_GetFirstTLV(hPeer), &g_tLLDP_TLVFilter_SystemCap); + if(ptTLVSysCap != NULL) + { + /* end station capability supported and end station capability marked as primary function */ + if( (NTOH16(ptTLVSysCap->usSystemCapabilites) & PN_PPSM_LLDP_ENDSTATION_BITMAP) && + (NTOH16(ptTLVSysCap->usEnabledCapabilites) & PN_PPSM_LLDP_ENDSTATION_BITMAP) ) + { + return true; + } + } + return false; +} + /** - * @brief Function to call when a data change of peer shall be indicated to the PPSM + * @brief Get peers name of station, if it exists. * - * @param ptPort Pointer to peer port resources - * @return False if no LLDP peer could be found, otherwise true. + * @param ptPort [in] handle of prot + * @param ppbNameOfStation [in/out] poniter wehre the name of station + * @param pbLenNameOfStation [in/out] handle of prot + * @return True if the name of station exists, otherwise False. */ -bool Pn_PPSM_UpdatePeerChange(PN_CORE_RSC_PORT_T *ptPort) +static void +Pn_GetPeer_NameOfStation(LLDP_PEER_H hPeer, uint8_t** ppbNameOfStation, uint8_t* pbLenNameOfStation) { - bool fRetval = false; - DRV_ETH_IOCTL_PRM_MCAST_FRWD_T tPrm; const uint8_t* pbNameOfStation = 0; uint8_t bLenNameOfStation = 0; - LLDP_H hLLDP = ptPort->tRem.hPnCore->tState.hLldp; + + const LLDP_PDU_TLV_CHASSISID_T* ptTLVChassisId; + const LLDP_PDU_TLV_PORTID_T* ptTLVPortId; + + ptTLVChassisId = LLDP_FindTLV(LLDP_Peer_GetFirstTLV(hPeer), &g_tLLDP_TLVFilter_ChassisId); + ptTLVPortId = LLDP_FindTLV((void*)ptTLVChassisId, &g_tLLDP_TLVFilter_PortId); + + /* Check whether the name of the station is reported using PortId TLV. */ + if(NULL != ptTLVPortId) + { + uint_fast16_t usLenPortId = LLDP_TypeLen_GetLen(ptTLVPortId->usTLVTypeLen) - sizeof(ptTLVPortId->bSubtype); + + if(ptTLVPortId->bSubtype == LLDP_TLV_PORT_ID_SUBTYPE_LOCALLY_ASSIGNED) + { + pbNameOfStation = memchr(ptTLVPortId->abPortId, '.', usLenPortId); + + if(pbNameOfStation != NULL) + { /* multiple interface mode */ + pbNameOfStation++; + bLenNameOfStation = usLenPortId - (pbNameOfStation - ptTLVPortId->abPortId); + } + } + } + + /* Check whether the name of the station is reported using ChassisId TLV. */ + if( (pbLenNameOfStation == 0) && ( NULL != ptTLVChassisId) && + (ptTLVChassisId->bSubtype == LLDP_TLV_CHASSIS_ID_SUBTYPE_LOCALLY_ASSIGNED)) + { + pbNameOfStation = ptTLVChassisId->abChassisId; + bLenNameOfStation = LLDP_TypeLen_GetLen(ptTLVChassisId->usTLVTypeLen) - sizeof(ptTLVChassisId->bSubtype); + } + + if( (NULL != pbNameOfStation) && (0 != bLenNameOfStation)) + { /* NameOfStation is known to us / available */ + *ppbNameOfStation = pbNameOfStation; + *pbLenNameOfStation = bLenNameOfStation; + } + else + { + *ppbNameOfStation = NULL; + *pbLenNameOfStation = 0; + } +} + +/** + * @brief Calculate a multicast MAC address from the given name of station + * + * Selector = MD5(NameOfStation) & 0x1F + * Selector - is the selector for the destination multicast MAC address + * MD5 - is the IETF RFC 6151 defined function to create a 128 bit fingerprint + * NameOfStation - is the variable length input parameter NameOfStation + * + * @param pbNameOfStation Name of station used for calculating the MAC address + * @param tLenNameOfStation Length of the given name of station + * @return 0 if an error occured, otherwise the last byte of a MAC address + */ +bool +Pn_PPSM_Get_FWD_MCASTAddr(PN_CORE_RSC_PORT_T *ptPort, ETH_MAC_ADDR_T *ptMacAddr) +{ + const uint8_t* pbNameOfStation = 0; + uint8_t bLenNameOfStation = 0; + bool fPeerIsEndStation; + LLDP_PEER_ITER_T tIter; LLDP_PEER_H hPeer; + LLDP_H hLLDP = ptPort->tRem.hPnCore->tState.hLldp; - tPrm.bPortMaskTo = ptPort->tRem.bPortIdx + 1; - tPrm.bPortMaskFrom = 2/tPrm.bPortMaskTo; + const LLDP_PDU_TLV_CHASSISID_T* ptTLVChassisId; + const LLDP_PDU_TLV_PORTID_T* ptTLVPortId; - // Disable all DCP multicast addresses in this rage - Pn_PPSM_DiasbleOtherPeerMcastAddrInRange(ptPort->tRem.hPnCore, &tPrm); - /* Get remote peers registered with LLDP on this port */ for(hPeer = LLDP_PeerIter_First(hLLDP, &tIter); hPeer != NULL; hPeer = LLDP_PeerIter_Next(hLLDP, &tIter)) { @@ -266,30 +292,56 @@ break; } - if(hPeer != NULL) + if (hPeer != NULL) { - PN_PPSM_TRUTH_TABLE_RESULT_T tResult; - fRetval = true; - const LLDP_PDU_TLV_CHASSISID_T *ptTLVChassisId = LLDP_FindTLV(LLDP_Peer_GetFirstTLV(hPeer), &g_tLLDP_TLVFilter_ChassisId); - const LLDP_PDU_TLV_SYSTEM_CAPABILITIES_T *ptTLVSysCap = LLDP_FindTLV((void*)ptTLVChassisId, &g_tLLDP_TLVFilter_SystemCap); + /* Get remote peers registered with LLDP on this port */ + Pn_GetPeer_NameOfStation(hPeer, &pbNameOfStation, &bLenNameOfStation); - tResult = Pn_PPSM_EvaluateTruthTable(ptTLVChassisId, ptTLVSysCap, &pbNameOfStation, &bLenNameOfStation); - - if(PN_PPSM_TRUTH_TABLE_RESULT_OPTIMIZED == tResult) + /* Check if neighbor at the given port is an end station */ + fPeerIsEndStation = Pn_Peer_isEndStation(hPeer); + + /* Evaluating a dedicated truth table defined within the PN spec "chapter 4.12.7.6 + Truth and behavior tables" "Table 457 PPSM truth table"*/ + if(pbNameOfStation != NULL && bLenNameOfStation != 0 && Pn_Peer_isEndStation(ptPort)) { - if(0 != Pn_PPSM_CalculateMulticastMACAddr(pbNameOfStation, bLenNameOfStation, &tPrm.tMacAddr)) + if(0 != Pn_PPSM_CalculateMulticastMACAddr(pbNameOfStation, bLenNameOfStation, ptMacAddr)) { // Activate only the calculated MAC address - uint32_t ulIoctlResult = Pn_Eth_Ioctl(ptPort->tRem.hPnCore, DRV_ETH_IOCTL_ENABLE_MCAST_FRWD, &tPrm, sizeof(tPrm)); - DBGLOG_DEBUG("Pns-PPSM: Enable DCP multicast frwd to Peer 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X, from port %d to %d, with result 0x%08X", - (unsigned int)tPrm.tMacAddr[0],(unsigned int)tPrm.tMacAddr[1],(unsigned int)tPrm.tMacAddr[2],(unsigned int)tPrm.tMacAddr[3],(unsigned int)tPrm.tMacAddr[4],(unsigned int)tPrm.tMacAddr[5], - tPrm.bPortMaskFrom, tPrm.bPortMaskTo, (unsigned int)ulIoctlResult); + return true; } } - else if(PN_PPSM_TRUTH_TABLE_RESULT_DEFAULT == tResult) - { - // Update_Static_Filtering_Entry_req (Port) equals to normal operation. - } } - return fRetval; + + return false; } + +/** + * @brief Function to call when a data change of peer shall be indicated to the PPSM + * + * @param ptPort Pointer to peer port resources + * @return False if no LLDP peer could be found, otherwise true. + */ +bool Pn_PPSM_UpdatePeerChange(PN_CORE_RSC_PORT_T *ptPort) +{ + DRV_ETH_IOCTL_PRM_MCAST_FRWD_T tPrm; + + /* Disable all DCP multicast addresses in this rage */ + { + tPrm.bPortMaskTo = ptPort->tRem.bPortIdx + 1; + tPrm.bPortMaskFrom = 2/tPrm.bPortMaskTo; + + Pn_PPSM_DiasbleOtherPeerMcastAddrInRange(ptPort->tRem.hPnCore, &tPrm); + } + + /* get DCP FWD MCAST Address based on the new peer name */ + if(Pn_PPSM_Get_FWD_MCASTAddr(ptPort, &tPrm.tMacAddr)) + { + // Activate only the calculated MAC address + uint32_t ulIoctlResult = Pn_Eth_Ioctl(ptPort->tRem.hPnCore, DRV_ETH_IOCTL_ENABLE_MCAST_FRWD, &tPrm, sizeof(tPrm)); + DBGLOG_DEBUG("Pns-PPSM: Enable DCP multicast frwd to Peer 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X, from port %d to %d, with result 0x%08X", + (unsigned int)tPrm.tMacAddr[0], (unsigned int)tPrm.tMacAddr[1], + (unsigned int)tPrm.tMacAddr[2], (unsigned int)tPrm.tMacAddr[3], + (unsigned int)tPrm.tMacAddr[4],(unsigned int)tPrm.tMacAddr[5], + tPrm.bPortMaskFrom, tPrm.bPortMaskTo, (unsigned int)ulIoctlResult); + } +} \ No newline at end of file