ptpd_net.c
来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 409 行
C
409 行
/* net.c */
#include "lwip/opt.h"
#include "lwip/stats.h"
#include "lwip/mem.h"
#include "lwip/udp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/inet.h"
#include "netif/etharp.h"
#include "lwip/sys.h"
#include "ptpd.h"
/* Network Buffer Queue Functions. */
static void netQInit(BufQueue *pQ)
{
pQ->get = 0;
pQ->put = 0;
pQ->count = 0;
}
static Integer32 netQPut(BufQueue *pQ, void *pbuf)
{
if(pQ->count >= PBUF_QUEUE_SIZE)
return FALSE;
pQ->pbuf[pQ->put] = pbuf;
pQ->put = (pQ->put + 1) % PBUF_QUEUE_SIZE;
pQ->count++;
return TRUE;
}
void *netQGet(BufQueue *pQ)
{
void *pbuf;
if(!pQ->count)
return NULL;
pbuf = pQ->pbuf[pQ->get];
pQ->get = (pQ->get + 1) % PBUF_QUEUE_SIZE;
pQ->count--;
return pbuf;
}
static Integer32 netQCheck(BufQueue *pQ)
{
if(!pQ->count)
return FALSE;
return TRUE;
}
/* Processing an incoming message on the Event port. */
static void eventRecv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *addr, u16_t port)
{
NetPath *netPath = (NetPath *)arg;
/* prevent warnings about unused arguments */
(void)pcb; (void)addr; (void)port;
/* Place the incoming message on the Event Port QUEUE. */
if(!netQPut(&netPath->eventQ, p))
PERROR("Event Queue Full!\n");
}
/* Processing an incoming message on the Event port. */
static void generalRecv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *addr, u16_t port)
{
NetPath *netPath = (NetPath *)arg;
/* prevent warnings about unused arguments */
(void)pcb; (void)addr; (void)port;
/* Place the incoming message on the Event Port QUEUE. */
if(!netQPut(&netPath->generalQ, p))
{
PERROR("Event Queue Full!\n");
}
}
Boolean lookupSubdomainAddress(Octet *subdomainName, Octet *subdomainAddress)
{
UInteger32 h;
/* set multicast group address based on subdomainName */
if (!memcmp(subdomainName, DEFAULT_PTP_DOMAIN_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, DEFAULT_PTP_DOMAIN_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN1_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN1_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN2_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN2_ADDRESS, NET_ADDRESS_LENGTH);
else if(!memcmp(subdomainName, ALTERNATE_PTP_DOMAIN3_NAME, PTP_SUBDOMAIN_NAME_LENGTH))
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN3_ADDRESS, NET_ADDRESS_LENGTH);
else
{
h = crc_algorithm(subdomainName, PTP_SUBDOMAIN_NAME_LENGTH) % 3;
switch(h)
{
case 0:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN1_ADDRESS, NET_ADDRESS_LENGTH);
break;
case 1:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN2_ADDRESS, NET_ADDRESS_LENGTH);
break;
case 2:
memcpy(subdomainAddress, ALTERNATE_PTP_DOMAIN3_ADDRESS, NET_ADDRESS_LENGTH);
break;
default:
ERROR("handle out of range for '%s'!\n", subdomainName);
return FALSE;
}
}
return TRUE;
}
Boolean netInit(NetPath *netPath, RunTimeOpts *rtOpts, PtpClock *ptpClock)
{
int i;
struct in_addr netAddr;
char addrStr[NET_ADDRESS_LENGTH];
DBG("netInit\n");
/* Allocate tx buffer for the event port. */
netPath->eventTxBuf = pbuf_alloc(PBUF_TRANSPORT, PACKET_SIZE, PBUF_RAM);
if(netPath->eventTxBuf == NULL)
{
PERROR("Failed to allocate Event Tx Buffer\n");
return FALSE;
}
/* Allocate tx buffer for the general port. */
netPath->generalTxBuf = pbuf_alloc(PBUF_TRANSPORT, PACKET_SIZE, PBUF_RAM);
if(netPath->generalTxBuf == NULL)
{
PERROR("Failed to allocate Event Tx Buffer\n");
pbuf_free(netPath->eventTxBuf);
return FALSE;
}
/* Open lwIP raw udp interfaces for the event port. */
netPath->eventPcb = udp_new();
if(netPath->eventPcb == NULL)
{
PERROR("Failed to open Event UDP PCB\n");
pbuf_free(netPath->eventTxBuf);
pbuf_free(netPath->generalTxBuf);
return FALSE;
}
/* Open lwIP raw udp interfaces for the general port. */
netPath->generalPcb = udp_new();
if(netPath->generalPcb == NULL)
{
PERROR("Failed to open General UDP PCB\n");
udp_remove(netPath->eventPcb);
pbuf_free(netPath->eventTxBuf);
pbuf_free(netPath->generalTxBuf);
return FALSE;
}
/* Initialize the buffer queues. */
netQInit(&netPath->eventQ);
netQInit(&netPath->generalQ);
/* Configure network (broadcast/unicast) addresses. */
netPath->unicastAddr = 0;
if(!lookupSubdomainAddress(rtOpts->subdomainName, addrStr))
{
udp_disconnect(netPath->eventPcb);
udp_disconnect(netPath->generalPcb);
udp_remove(netPath->eventPcb);
udp_remove(netPath->generalPcb);
pbuf_free(netPath->eventTxBuf);
pbuf_free(netPath->generalTxBuf);
return FALSE;
}
if(!inet_aton(addrStr, &netAddr))
{
ERROR("failed to encode multi-cast address: %s\n", addrStr);
udp_disconnect(netPath->eventPcb);
udp_disconnect(netPath->generalPcb);
udp_remove(netPath->eventPcb);
udp_remove(netPath->generalPcb);
pbuf_free(netPath->eventTxBuf);
pbuf_free(netPath->generalTxBuf);
return FALSE;
}
netPath->multicastAddr = netAddr.s_addr;
/* Setup subdomain address string. */
for(i = 0; i < SUBDOMAIN_ADDRESS_LENGTH; ++i)
{
ptpClock->subdomain_address[i] = (netAddr.s_addr >> (i * 8)) & 0xff;
}
/* Establish the appropriate UDP bindings/connections for events. */
udp_recv(netPath->eventPcb, eventRecv, netPath);
udp_bind(netPath->eventPcb, IP_ADDR_ANY, PTP_EVENT_PORT);
udp_connect(netPath->eventPcb, IP_ADDR_ANY, PTP_EVENT_PORT);
*(Integer16*)ptpClock->event_port_address = PTP_EVENT_PORT;
/* Establish the appropriate UDP bindings/connections for general. */
udp_recv(netPath->generalPcb, generalRecv, netPath);
udp_bind(netPath->generalPcb, IP_ADDR_ANY, PTP_GENERAL_PORT);
udp_connect(netPath->generalPcb, IP_ADDR_ANY, PTP_GENERAL_PORT);
*(Integer16*)ptpClock->general_port_address = PTP_GENERAL_PORT;
/* Return a success code. */
return TRUE;
}
/* shut down the UDP stuff */
Boolean netShutdown(NetPath *netPath)
{
/* Disconnect and close the Event UDP interface */
if(netPath->eventPcb)
{
udp_disconnect(netPath->eventPcb);
udp_remove(netPath->eventPcb);
}
/* Disconnect and close the General UDP interface */
if(netPath->generalPcb)
{
udp_disconnect(netPath->generalPcb);
udp_remove(netPath->generalPcb);
}
/* Free up the Event and General Tx PBUFs. */
if(netPath->eventTxBuf)
{
pbuf_free(netPath->eventTxBuf);
}
if(netPath->generalTxBuf)
{
pbuf_free(netPath->generalTxBuf);
}
/* Clear the network addresses. */
netPath->multicastAddr = 0;
netPath->unicastAddr = 0;
/* Return a success code. */
return TRUE;
}
/* Wait for a packet to come in on either port. For now, there is no wait.
* Simply check to see if a packet is available on either port and return 1,
* otherwise return 0. */
int netSelect(TimeInternal *timeout, NetPath *netPath)
{
/* Check the packet queues. If there is data, return TRUE. */
if(netQCheck(&netPath->eventQ) || netQCheck(&netPath->generalQ))
return 1;
return 0;
}
/* Pop a message off of the event queue and copy it to the passed in buffer. */
size_t netRecvEvent(Octet *buf, TimeInternal *time, NetPath *netPath)
{
int i, j;
int iPacketSize;
struct pbuf *p, *pcopy;
/* Attempt to get a buffer from the Q. If none is available,
* return length of 0. */
p = netQGet(&netPath->eventQ);
if(p == NULL)
return 0;
pcopy = p;
/* Here, p points to a valid PBUF structure. Verify that we have
* enough space to store the contents. */
if(p->tot_len > PACKET_SIZE)
{
ERROR("received truncated message\n");
return 0;
}
/* Copy the PBUF payload into the buffer. */
j = 0;
iPacketSize = p->tot_len;
for(i = 0; i < iPacketSize; i++)
{
buf[i] = ((u8_t *)pcopy->payload)[j++];
if(j == pcopy->len)
{
pcopy = pcopy->next;
j = 0;
}
}
/* Get the timestamp information. */
time->seconds = p->timestamp.seconds;
time->nanoseconds = p->timestamp.nanoseconds;
/* Free up the pbuf (chain). */
pbuf_free(p);
/* Return the length of data copied. */
return iPacketSize;
}
/* Pop a message off of the general queue and copy to the passed in buffer. */
size_t netRecvGeneral(Octet *buf, NetPath *netPath)
{
int i, j;
int iPacketSize;
struct pbuf *p, *pcopy;
/* Attempt to get a buffer from the Q. If none is available,
* return length of 0. */
p = netQGet(&netPath->generalQ);
if(p == NULL)
return 0;
pcopy = p;
/* Here, p points to a valid PBUF structure. Verify that we have
* enough space to store the contents. */
if(p->tot_len > PACKET_SIZE)
{
ERROR("received truncated message\n");
return 0;
}
/* Copy the PBUF payload into the buffer. */
j = 0;
iPacketSize = p->tot_len;
for(i = 0; i < iPacketSize; i++)
{
buf[i] = ((u8_t *)pcopy->payload)[j++];
if(j == pcopy->len)
{
pcopy = pcopy->next;
j = 0;
}
}
/* Free up the pbuf (chain). */
pbuf_free(p);
/* Return the length of data copied. */
return iPacketSize;
}
/* Transmit a packet on the Event Port. */
size_t netSendEvent(Octet *buf, UInteger16 length, NetPath *netPath)
{
int i, j;
struct pbuf *pcopy;
/* Reallocate the tx pbuf based on the current size. */
pbuf_realloc(netPath->eventTxBuf, length);
pcopy = netPath->eventTxBuf;
/* Copy the incoming data into the pbuf payload. */
j = 0;
for(i = 0; i < length; i++)
{
((u8_t *)pcopy->payload)[j++] = buf[i];
if(j == pcopy->len)
{
pcopy = pcopy->next;
j = 0;
}
}
/* send the buffer. */
udp_sendto(netPath->eventPcb, netPath->eventTxBuf,
(void *)&netPath->multicastAddr, PTP_EVENT_PORT);
return(length);
}
/* Transmit a packet on the General Port. */
size_t netSendGeneral(Octet *buf, UInteger16 length, NetPath *netPath)
{
int i, j;
struct pbuf *pcopy;
/* Reallocate the tx pbuf based on the current size. */
pbuf_realloc(netPath->generalTxBuf, length);
pcopy = netPath->generalTxBuf;
/* Copy the incoming data into the pbuf payload. */
j = 0;
for(i = 0; i < length; i++)
{
((u8_t *)pcopy->payload)[j++] = buf[i];
if(j == pcopy->len)
{
pcopy = pcopy->next;
j = 0;
}
}
/* send the buffer. */
udp_sendto(netPath->eventPcb, netPath->generalTxBuf,
(void *)&netPath->multicastAddr, PTP_GENERAL_PORT);
return(length);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?