PTPD2源码解析之:packet的接收和发送

整个流程大概是:

  • do_state(ptp_master状态)

    • issueAnnounce

      • netSendGeneral
    • handle

      • netRecvGeneral
ssize_t 
netSendGeneral(Octet * buf, UInteger16 length, NetPath * netPath,
           const const RunTimeOpts *rtOpts, Integer32 destinationAddress)
{
    ssize_t ret;
    struct sockaddr_in addr;

    addr.sin_family = AF_INET;
    addr.sin_port = htons(PTP_GENERAL_PORT);

#ifdef PTPD_PCAP
    if ((netPath->pcapGeneral != NULL) && (rtOpts->transport == IEEE_802_3)) {
        ret = netSendPcapEther(buf, length,
            &netPath->etherDest,
            (struct ether_addr *)netPath->interfaceID,
            netPath->pcapGeneral);

        if (ret <= 0) 
            DBG("Error sending ether multicast general message\n");
        else {
            netPath->sentPackets++;
            netPath->sentPacketsTotal++;
        }
    } else {
#endif
        if(destinationAddress) {

            addr.sin_addr.s_addr = destinationAddress;
            /*
             * This function is used for PTP only anyway...
             * If we're sending to a unicast address, set the UNICAST flag.
             */
            *(char *)(buf + 6) |= PTP_UNICAST;

            ret = sendto(netPath->generalSock, buf, length, 0, 
                     (struct sockaddr *)&addr, 
                     sizeof(struct sockaddr_in));
            if (ret <= 0)
                DBG("Error sending unicast general message\n");
            else {
                netPath->sentPackets++;
                netPath->sentPacketsTotal++;
            }
        } else {
            addr.sin_addr.s_addr = netPath->multicastAddr;

                        /* Is TTL OK? */
            if(netPath->ttlGeneral != rtOpts->ttl) {
                /* Try restoring TTL */
                if (netSetMulticastTTL(netPath->generalSock,rtOpts->ttl)) {
                    netPath->ttlGeneral = rtOpts->ttl;
                }
                    }

            ret = sendto(netPath->generalSock, buf, length, 0, 
                     (struct sockaddr *)&addr, 
                     sizeof(struct sockaddr_in));
            if (ret <= 0)
                DBG("Error sending multicast general message\n");
            else {
                netPath->sentPackets++;
                netPath->sentPacketsTotal++;
            }
        }

#ifdef PTPD_PCAP
    }
#endif
    return ret;
}
  • 上面是发送网络包的源码,其中ret是为了配合接收packet而返回的文件描述字(符合Linux一切皆是文件的理念)。
  • 其中PTPD_PCAP那部分不重要,貌似没有作用,暂不了解。
  • 有destinationAddress就unicast,没有multicast。
ssize_t 
netRecvGeneral(Octet * buf, NetPath * netPath)
{
    ssize_t ret = 0;
    struct sockaddr_in from_addr;

#ifdef PTPD_PCAP
    struct pcap_pkthdr *pkt_header;
    const u_char *pkt_data;
#endif
    socklen_t from_addr_len = sizeof(from_addr);

    netPath->lastSourceAddr = 0;

#ifdef PTPD_PCAP
    if (netPath->pcapGeneral == NULL) {
#endif
        ret=recvfrom(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT, (struct sockaddr*)&from_addr, &from_addr_len);
        netPath->lastSourceAddr = from_addr.sin_addr.s_addr;
        /* do not report "from self" */
        if(!netPath->lastSourceAddr || (netPath->lastSourceAddr != netPath->interfaceAddr.s_addr)) {
            netPath->receivedPackets++;
        }
        netPath->receivedPacketsTotal++;
        return ret;
#ifdef PTPD_PCAP
    }
#endif

#ifdef PTPD_PCAP
    else { /* Using PCAP */
        /* Discard packet on socket */
        if (netPath->generalSock >= 0)
            recv(netPath->generalSock, buf, PACKET_SIZE, MSG_DONTWAIT);

        
        if (( ret = pcap_next_ex(netPath->pcapGeneral, &pkt_header, 
                     &pkt_data)) < 1) {
            if (ret < 0) 
                DBGV("netRecvGeneral: pcap_next_ex failed %d %s\n",
                     ret, pcap_geterr(netPath->pcapGeneral));
            return 0;
        }

    /* Make sure this is IP (could dot1q get here?) */
    if( ntohs(*(u_short *)(pkt_data + 12)) != ETHERTYPE_IP) {
        if( ntohs(*(u_short *)(pkt_data + 12)) != PTP_ETHER_TYPE) {
        DBG("PCAP payload ethertype received not IP or PTP: 0x%04x\n",
            ntohs(*(u_short *)(pkt_data + 12)));
        /* do not count packets if from self */
        } else if(memcmp(&netPath->interfaceInfo.hwAddress, pkt_data + 6, 6)) {
            netPath->receivedPackets++;
        }
    } else {
        /* Retrieve source IP from the payload - 14 eth + 12 IP */
        netPath->lastSourceAddr = *(Integer32 *)(pkt_data + 26);
        /* Retrieve destination IP from the payload - 14 eth + 16 IP */
        netPath->lastDestAddr = *(Integer32 *)(pkt_data + 30);
        /* do not count packets from self */
        if(netPath->lastSourceAddr != netPath->interfaceAddr.s_addr) {
            netPath->receivedPackets++;
        }
    }

    netPath->receivedPacketsTotal++;

        /* XXX Total cheat */
        memcpy(buf, pkt_data + netPath->headerOffset, 
               pkt_header->caplen - netPath->headerOffset);
        fflush(NULL);
        ret = pkt_header->caplen - netPath->headerOffset;
    }
#endif
    return ret;
}
  • 上面是接收

相关推荐