LOCAL void mirrorEndReceive ( END_CTRL* pDrvCtrl, /* pointer to END_CTRL structure */ M_BLK* pMblk ) { UINT16 * pTmp; UINT16 enetAddr[3]; LOG_MSG("mirrorEndReceive: unit: %d, ", (int)pDrvCtrl->unit, 2, 3, 4, 5, 6); LOG_MSG("dst:%02X:%02X:%02X:%02X:%02X:%02X, ", *(UCHAR *)(pMblk->mBlkHdr.mData), *((UCHAR *)(pMblk->mBlkHdr.mData) + 1), *((UCHAR *)(pMblk->mBlkHdr.mData) + 2), *((UCHAR *)(pMblk->mBlkHdr.mData) + 3), *((UCHAR *)(pMblk->mBlkHdr.mData) + 4), *((UCHAR *)(pMblk->mBlkHdr.mData) + 5)); LOG_MSG("src:%02X:%02X:%02X:%02X:%02X:%02X\n", *((UCHAR *)(pMblk->mBlkHdr.mData) + 6), *((UCHAR *)(pMblk->mBlkHdr.mData) + 7), *((UCHAR *)(pMblk->mBlkHdr.mData) + 8), *((UCHAR *)(pMblk->mBlkHdr.mData) + 9), *((UCHAR *)(pMblk->mBlkHdr.mData) + 10), *((UCHAR *)(pMblk->mBlkHdr.mData) + 11)); /* don't allow the packet through if in polling mode */ if (pDrvCtrl->polling == TRUE) { netMblkClChainFree(pMblk); return; } /* if unit is not in promiscuous mode, filter packets to receive only * packets for our MAC address or broadcasts. */ if (pDrvCtrl->promiscuous == FALSE) { pTmp = (UINT16 *)(pMblk->mBlkHdr.mData); if (((UINT32)(pTmp) & 0x01) == 0) { /* address is aligned on a 2 or 4 byte boundary */ enetAddr[0] = pTmp[0]; enetAddr[1] = pTmp[1]; enetAddr[2] = pTmp[2]; } else { /* address is aligned on a byte-boundary */ bcopy((char *)pTmp, (char *)enetAddr, 6); } if ((MAC_ADDR_EQ(enetAddr, pDrvCtrl->enetAddr) == 0) && (IS_BROADCAST(enetAddr) == 0) && (isInMulticastList(pDrvCtrl, enetAddr) == FALSE)) { LOG_MSG("Dest addr not my addr/broadcast/multicast - dropping!\n", 1, 2, 3, 4, 5, 6); netMblkClChainFree(pMblk); return; } } LOG_MSG("Sending up the packet to my network stack\n", 1, 2, 3, 4, 5, 6); /* send up to protocol */ END_RCV_RTN_CALL(&pDrvCtrl->endObject, pMblk); /* bump input packet counter */ END_ERR_ADD(&pDrvCtrl->endObject, MIB2_IN_UCAST, +1); }
LOCAL STATUS mirrorEndSend ( END_CTRL* pDrvCtrl, M_BLK* pMblk ) { int otherHalfOfMirror; int status = OK; LOG_MSG("mirrorEndSend: unit: %d, pollMode: %d, ", (int)pDrvCtrl->unit, (int)pDrvCtrl->polling, 4, 5, 6, 7); LOG_MSG("dst:%02X:%02X:%02X:%02X:%02X:%02X, ", *(UCHAR *)(pMblk->mBlkHdr.mData), *((UCHAR *)(pMblk->mBlkHdr.mData) + 1), *((UCHAR *)(pMblk->mBlkHdr.mData) + 2), *((UCHAR *)(pMblk->mBlkHdr.mData) + 3), *((UCHAR *)(pMblk->mBlkHdr.mData) + 4), *((UCHAR *)(pMblk->mBlkHdr.mData) + 5)); LOG_MSG("src:%02X:%02X:%02X:%02X:%02X:%02X\n", *((UCHAR *)(pMblk->mBlkHdr.mData) + 6), *((UCHAR *)(pMblk->mBlkHdr.mData) + 7), *((UCHAR *)(pMblk->mBlkHdr.mData) + 8), *((UCHAR *)(pMblk->mBlkHdr.mData) + 9), *((UCHAR *)(pMblk->mBlkHdr.mData) + 10), *((UCHAR *)(pMblk->mBlkHdr.mData) + 11)); if (pDrvCtrl->polling == TRUE) { netMblkClChainFree (pMblk); /* free the given mBlk chain */ return ERROR; } otherHalfOfMirror = pDrvCtrl->unit ^ 1; /* 0->1, 1->0 */ if (channelState[otherHalfOfMirror] == CHANNEL_UP) { /* other half of mirror is up, send packet there */ if (pDrvCtrl->unit == MIRROR_STACK_UNIT_NUM) mirrorSendStatus = OK; /* * In the previous version of the Bridge, calling mirrorEndReceive * directly caused deadlock when bridge tries to flood multicasts * outgoing from local stack. One way to avoid the deadlock is to * call mirrorEndReceive from tNetTask by using netJobAdd. But this * causes performance hit, and also overloads the netJob ring buffer. * * The better solution is to call mirrorEndReceive directly, and * avoid deadlock by not taking the bridge port list semaphore when * flooding packets to all bridge ports. Taking this semaphore was * previously thought necessary to guard against removal of a bridge * port when the bridge is flooding packets to that port. The * possibility of this occurring is very small, and can be avoided * if the user makes sure the bridge port is free of incoming and * outgoing traffic before removing the bridge port. */ mirrorEndReceive(&drvCtrl[otherHalfOfMirror], pMblk); if (pDrvCtrl->unit == MIRROR_STACK_UNIT_NUM) status = mirrorSendStatus; } else { /* other half of mirror is not up, toss the packet */ netMblkClChainFree(pMblk); } /* Bump the statistic counter. */ END_ERR_ADD(&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); return status; }
/* Free the packet. Free the packettags from the chained packets */ void osl_pktfree(M_BLK_ID m) /* PED: remove osh parameter */ { netMblkClChainFree(m); }
void osl_pktfree(void *drv, M_BLK_ID m, bool send) { netMblkClChainFree(m); }
STATUS socend_send(_END_OBJ_PAR *p, M_BLK_ID mb) /* * Function: socend_send * Purpose: SENS send packet interface to SOC device. * Parameters: p - pointer to VxWorks end_obj structure for device * mb - mBlk containing packet. * Returns: OK/ERROR * * Notes: Since since we don't have scatter/gather capability right * now, we must copy up the data into one clustered buffer. * If Possible, we simply hand off the buffer. */ { int rv; struct end_object *eo = (struct end_object *)p; socend_t *se = (socend_t *)eo->devObject.pDevice; char *packet; int l; enet_hdr_t *eh; void *cookie; bcm_pkt_t *pkt; if (NULL == (pkt = sal_alloc(sizeof(bcm_pkt_t), "bcm pkt"))) { return(ENOMEM); } /* * If there is more than one cluster, we must allocate another * buffer and copy the data. * * Note: Requires entire ethernet header to be in first mblk. */ if (mb->mBlkHdr.mNext|| !ENET_TAGGED((enet_hdr_t *)mb->mBlkHdr.mData)) { if (SOC_IS_ESW(se->se_unit)) { socend_packet_alloc(se->se_unit,SOC_END_PK_SZ, 0, (void*)&packet); } else { packet = soc_cm_salloc(se->se_unit, SOC_END_PK_SZ, "SOCEND_TX"); } if (NULL == (packet)) { END_ERR_ADD(eo, MIB2_OUT_ERRS, +1); netMblkClChainFree(mb); return(ENOMEM); } cookie = NULL; /* * If packet is not tagged, build a tag now. */ eh = (enet_hdr_t *)packet; if (!ENET_TAGGED((enet_hdr_t *)mb->mBlkHdr.mData)) { /* Set COS to default here */ l = ENET_TAG_SIZE + netMblkToBufCopy(mb, packet + ENET_TAG_SIZE, NULL); /* Copy MAC addresses */ sal_memcpy(eh, mb->mBlkHdr.mData, sizeof(sal_mac_addr_t) * 2); /* Set VLAN info */ eh->en_tag_tpid = htons(ENET_DEFAULT_TPID); eh->en_tag_ctrl = htons(VLAN_CTRL(0,0,se->se_vlan)); eh->en_tag_len = ((enet_hdr_t *)mb->mBlkHdr.mData)->en_untagged_len; } else { /* Just copy entire packet */ /* Extract priority and map to COS here */ l = netMblkToBufCopy(mb, packet, NULL); } if (set_target_broadcast && sal_memcmp(eh->en_dhost, eh->en_shost, 6) == 0) { sal_memcpy(eh->en_dhost, mac_ones, 6); } netMblkClChainFree(mb); /* Free MBLK */ } else { l = mb->mBlkHdr.mLen; packet = mb->mBlkHdr.mData; cookie = (void *)mb; } #if defined(BROADCOM_DEBUG) if (LOG_CHECK(BSL_LS_SYS_END | BSL_INFO) && LOG_CHECK(BSL_LS_SOC_PACKET | BSL_INFO)) { d_packet_format("socend TX", DECODE_ETHER, packet, l, NULL); } #endif /* defined(BROADCOM_DEBUG) */ if (snoop_ip_tx != NULL) { snoop_ip_tx(se->se_unit, packet, l); } sal_memset(pkt, 0, sizeof(bcm_pkt_t)); pkt->pkt_data = &(pkt->_pkt_data); pkt->_pkt_data.len = l; pkt->_pkt_data.data = (uint8 *)packet; pkt->blk_count = 1; pkt->unit = se->se_unit; pkt->pkt_len = l; SOC_PBMP_CLEAR(pkt->tx_pbmp); SOC_PBMP_CLEAR(pkt->tx_upbmp); SOC_PBMP_CLEAR(pkt->tx_l3pbmp); /* get tx_pbmp, tx_upbmp */ eh = (enet_hdr_t *)packet; rv = _socend_l2_lookup(se->se_unit, eh->en_dhost, VLAN_CTRL_ID(se->se_vlan), pkt); if(rv == ERROR){ LOG_CLI((BSL_META("socend_send : can't get egress port(s) by _socend_l2_lookup.\n"))); return(ERROR); } pkt->cookie = cookie; pkt->call_back = socend_send_done; pkt->flags &= ~BCM_TX_CRC_FLD; pkt->flags |= BCM_TX_CRC_APPEND; if ((rv = bcm_tx(se->se_unit, pkt, cookie)) != BCM_E_NONE) { LOG_ERROR(BSL_LS_SOC_COMMON, (BSL_META("bcm_tx failed: Unit %d: %s\n"), se->se_unit, bcm_errmsg(rv))); return(ERROR); } return(OK); }