LOCAL BOOL wdbEndPollArpReply ( struct mbuf * pMblk, void * pCookie ) { struct ether_header * pEh; struct ether_arp * pEa; WDB_END_PKT_DEV * pPktDev = pEndPktDev; int op; pEh = mtod(pMblk, struct ether_header *); pEa = (struct ether_arp *) ((char *)pEh + sizeof (struct ether_header)); op = ntohs(pEa->arp_op); /* test if the request is for us */ if ((bcmp ((caddr_t)&pPktDev->ipAddr.s_addr, (caddr_t)&pEa->arp_tpa, pEa->arp_pln) == 0) && (op == ARPOP_REQUEST)) { /* build the reply */ /* fill the ethernet header */ bcopy (pEh->ether_shost, pEh->ether_dhost, sizeof(pEh->ether_shost)); bcopy (pPktDev->srcAddr->mBlkHdr.mData, pEh->ether_shost, sizeof(pEh->ether_shost)); /* fill the ARP Frame */ bcopy (pEh->ether_dhost, pEa->arp_tha, pEa->arp_hln); bcopy (pEa->arp_spa, pEa->arp_tpa, pEa->arp_pln); bcopy (pEh->ether_shost, pEa->arp_sha, pEa->arp_hln); bcopy ((char *)&pPktDev->ipAddr.s_addr, pEa->arp_spa, pEa->arp_pln); pEa->arp_op = htons (ARPOP_REPLY); /* send the reply */ muxPollSend (pCookie, pMblk); netMblkClFree (pMblk); DRIVER_RESET_INPUT(pPktDev); return (TRUE); } netMblkClFree (pMblk); DRIVER_RESET_INPUT(pPktDev); return (FALSE); }
LOCAL STATUS NetdrvPollSend(END_DEVICE* pDrvCtrl, /* device to be polled */ M_BLK_ID pMblk /* packet to send */) { int len; u_short stat; #ifdef BOOTROM_DEBUG printf("\r\nNetdrvPollSend"); #endif stat = NetdrvStatusRead(pDrvCtrl); /* dummy code */ if((stat & NETDRV_TINT) == 0) { return ((STATUS) EAGAIN); } len = max(ETHERSMALL, pMblk->m_len); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); /* Free the data if it was accepted by device */ netMblkClFree (pMblk); #ifdef BOOTROM_DEBUG printf("\r\nleaving NetdrvPollSend"); #endif return (OK); }
void socend_receive_netjob(int pi, int pckti, int pckt_size) /* * Function: socend_receive_netjob * Purpose: Called from netjob after packet arrives. * Parameters: p - pointer to (se), cookied passed on registration * pckpi - pointer to packet data (int form). * pckt_size - received length of packet. * Returns: Nothing */ { socend_t *se = (socend_t *)pi; struct end_object *eo = &se->se_eo; void *pckt = (void *)pckti; bcm_vlan_t vid; CL_BLK_ID cb = NULL; M_BLK_ID mb = NULL; /* Check the DCB for errors */ #if defined(BROADCOM_DEBUG) /* Only compile in for debug */ if (LOG_CHECK(BSL_LS_SYS_END | BSL_INFO) && LOG_CHECK(BSL_LS_SOC_PACKET | BSL_INFO)) { d_packet_format("socend RX", DECODE_ETHER, pckt, pckt_size, NULL); } #endif /* BROADCOM_DEBUG */ /* * Build Cluster - then attach to mblks, 1 for each interface that * should get the packet. Broadcast/Multicast packets go up all the stacks. * * For multicast, it should only go up stacks that have registered for that * address, but for now, this will allow multiple interfaces to work. */ if ((NULL == (cb = netClBlkGet(eo->pNetPool, M_DONTWAIT)))) { if (mb) netMblkFree(eo->pNetPool, mb); netClFree(eo->pNetPool, pckt); /* Free packet */ END_ERR_ADD(eo, MIB2_IN_ERRS, +1); return; } #if defined(__mips__) if (SOC_IS_ESW(se->se_unit)) { seu_t *seu = &socend_seu[se->se_unit]; void *tmp; sal_memcpy((UINT8 *)seu->pkt_align_buf + 2, (UINT8 *)pckt, pckt_size); tmp = seu->pkt_align_buf; seu->pkt_align_buf = pckt; pckt = tmp; } #endif /* __mips__ */ /* 1 MBLK for each interface */ if ((mb = mBlkGet(eo->pNetPool, M_DONTWAIT, MT_DATA))) { netClBlkJoin(cb, pckt, SOC_END_PK_SZ, NULL, 0, 0, 0); netMblkClJoin(mb, cb); mb->mBlkPktHdr.len = mb->mBlkHdr.mLen = pckt_size; mb->mBlkHdr.mFlags |= M_PKTHDR; #if defined(__mips__) if (SOC_IS_ESW(se->se_unit)) { mb->mBlkHdr.mData +=2; } #endif /* __mips__ */ vid = VLAN_CTRL_ID(soc_ntohs(((enet_hdr_t *)mb->mBlkHdr.mData)->en_tag_ctrl)); if (SOC_IS_ESW(se->se_unit)) { socend_untag(mb); /* Untag packet for now */ } else { robo_socend_untag(mb); /* Untag packet for now */ } } else { netClBlkFree(eo->pNetPool, cb); netClFree(eo->pNetPool, pckt); /* Free packet */ return; } { M_BLK_ID tmb, fmb = mb; seu_t *seu = &socend_seu[se->se_unit]; /* * Duplicate MBLK, and point to same cluster. */ for (se = seu->seu_devices; se != NULL; se = se->se_next) { if (vid != se->se_vlan) { continue; } eo = &se->se_eo; if (se->se_next != NULL) { tmb = mBlkGet(eo->pNetPool, M_DONTWAIT, MT_DATA); netMblkDup(mb, tmb); } else { fmb = NULL; tmb = mb; } END_RCV_RTN_CALL(eo, tmb); } if (fmb) { netMblkClFree(fmb); } } }
int wdbEndInt ( void * pCookie, long type, M_BLK_ID pMblk, LL_HDR_INFO * pLinkHdrInfo, void * pMode ) { struct mbuf * pMbuf; int size; struct udphdr * pUdpHdr; struct ip * pIpHdr; WDB_END_PKT_DEV * pPktDev = pEndPktDev; /* input buffer already in use - drop this packet */ if (wdbEndDebug) logMsg ("Got a packet!\n", 1, 2, 3, 4, 5, 6); if (pPktDev->inputBusy) { if (wdbEndDebug) logMsg ("Input busy!\n", 1, 2, 3, 4, 5, 6); /* * free the packet only if the driver is in polling mode. If not, the * packet will be freed by the MUX layer. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); return (FALSE); } pPktDev->inputBusy = TRUE; /* Check the type before doing anything expensive. */ if ((type == 0x806) && (pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) { /* * In polling mode we need to answer ARP request so that * communication becomes or remains possible. */ if (wdbEndDebug) logMsg ("Type == 0x806\n", 1, 2, 3, 4, 5, 6); return (wdbEndPollArpReply (pMblk, pCookie)); } if (type != 0x800) { if (wdbEndDebug) logMsg ("Type != 0x800 && Type!= 0x806\n", 1, 2, 3, 4, 5, 6); goto wdbEndIntError; } size = pLinkHdrInfo->dataOffset + IP_HDR_SIZE + sizeof(struct udphdr); if (!(pMblk->mBlkHdr.mFlags & M_PKTHDR) || (pMblk->mBlkPktHdr.len < size)) { goto wdbEndIntError; } if (pMblk->mBlkHdr.mLen < size) { if (netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, size, NULL) == 0) goto wdbEndIntError; pIpHdr = (struct ip *) pInPkt; pUdpHdr = (struct udphdr *)(pInPkt + IP_HDR_SIZE); } else { pIpHdr = (struct ip *) (pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset); pUdpHdr = (struct udphdr *)(pMblk->mBlkHdr.mData + pLinkHdrInfo->dataOffset + IP_HDR_SIZE); } /* If this packet is not for the agent, ignore it */ if ((pIpHdr->ip_p != IPPROTO_UDP) || (pUdpHdr->uh_dport != htons(WDBPORT))) goto wdbEndIntError; if (pPktDev->ipAddr.s_addr != pIpHdr->ip_dst.s_addr) goto wdbEndIntError; /* * Check to see whether the packet is fragmented. WDB does not * handle fragmented packets. */ if (pIpHdr->ip_off & htons(IP_MF|IP_OFFMASK)) { if (wdbEndDebug) logMsg ("Fragmented packet\n", 0, 0, 0, 0, 0, 0); goto wdbEndIntError; } if ((size = netMblkOffsetToBufCopy (pMblk, pLinkHdrInfo->dataOffset, pInPkt, M_COPYALL, NULL)) == 0) goto wdbEndIntError; bcopy ((char *)pMblk->mBlkHdr.mData + pLinkHdrInfo->srcAddrOffset, (char *)pPktDev->lastHAddr->mBlkHdr.mData, pLinkHdrInfo->srcSize); /* We're always going to send an IP packet. */ pPktDev->lastHAddr->mBlkHdr.reserved = htons (0x800); /* * Fill the input buffer with the packet. Use an mbuf cluster * to pass the packet on to the agent. */ pMbuf = wdbMbufAlloc (); if (pMbuf == NULL) goto wdbEndIntError; wdbMbufClusterInit (pMbuf, pInPkt, size, (int (*)())wdbEndInputFree, (int)pPktDev); if (wdbEndDebug) logMsg ("Passing up a packet!\n", 1, 2, 3, 4, 5, 6); (*pPktDev->wdbDrvIf.stackRcv) (pMbuf); /* invoke callback */ netMblkClFree (pMblk); return (TRUE); wdbEndIntError: { /* * drop all non wdb packets received through the poll routine * When call from muxReceive pMode is actually the spare pointer * which is initialized in the NET_PROTOCOL structure, the spare * pointer is passed as the last argument to the stackRcvRtn. * When called from wdbEndPoll it passes a mode in the void pointer * This mode is used to find out whether this routine is called from * wdbEndPoll or muxReceive. You will not be happy camper if the * spare pointer is removed from NET_PROTOCOL or if the stackRcvRtn's * API is changed. */ if ((pMode != NULL) && (*((int *)pMode) == WDB_COMM_MODE_POLL)) netMblkClFree (pMblk); DRIVER_RESET_INPUT(pPktDev); return (FALSE); } }