distIfUdp.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:18k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* distIfUdp.c - distributed objects UDP adapter library (VxFusion option) */
  2. /* Copyright 1999-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01l,22oct01,jws  fix diab compiler warnings (SPR 71117)
  7. 01k,11jun99,drm  Changing flags to host byte order before checking for
  8.                  broadcast flag.
  9. 01j,24may99,drm  Adding vxfusion prefix to VxFusion related includes.
  10. 01i,19may99,drm  Changing WindMP to VxFusion.
  11. 01h,25feb99,drm  added additional status output during initialization
  12. 01g,22feb99,drm  adding #include for distNetLib.h
  13. 01f,30oct98,drm  documentation updates
  14. 01e,29oct98,drm  removed maxTBufs argument to distIfUdpInit
  15. 01d,01sep98,drm  removed pDistIf definition
  16. 01c,04aug98,drm  cleanup and bug fixes
  17. 01b,20may98,drm  removed compiler warning messages
  18. 01a,04apr98,jag  written.
  19. */
  20. /*
  21. DESCRIPTION
  22. This module implements a UDP adapter for VxFusion.  This is the default 
  23. adapter that VxFusion uses when it starts up.
  24. There are only two external routines: distIfUdpInit() and distIfUdpStart().
  25. Both are called by the VxFusion initialization routine distInit() and should 
  26. not be called directly by the user.
  27. AVAILABILITY
  28. This module is distributed as a component of the unbundled distributed
  29. message queues option, VxFusion.
  30. INCLUDE FILES: distIfUdp.h
  31. SEE ALSO: distLib
  32. */
  33. /* includes */
  34. #include "vxWorks.h"
  35. #include "string.h"
  36. #include "stdio.h"
  37. #include "taskLib.h"
  38. #include "sysLib.h"
  39. #include "inetLib.h"
  40. #include "sockLib.h"
  41. #include "netLib.h"
  42. #include "ioLib.h"
  43. #include "wdLib.h"
  44. #include "usrLib.h"
  45. #include "sys/ioctl.h"
  46. #include "netinet/in.h"
  47. #include "net/if.h"
  48. #include "selectLib.h"
  49. #include "errnoLib.h"
  50. #include "vxfusion/distIfLib.h"
  51. #include "vxfusion/distStatLib.h"
  52. #include "vxfusion/distNetLib.h"
  53. #include "drv/vxfusion/distIfUdp.h"
  54. /* defines */
  55. #define UNUSED_ARG(x)  if (sizeof(x)) {};  /* suppress compiler warning */
  56. #define SOCKOPT_ON  1                   /* 1 = on for setsockopt() */
  57. #define sleep(timeO) taskDelay (timeO * (sysClkRateGet())) /* macro */
  58. /* locals */
  59. LOCAL DIST_IF distIfUdp;                /* used to set pDistIf */
  60. LOCAL BOOL distIfUdpInstalled = FALSE;  /* indicates whether driver installed */
  61. LOCAL BOOL distIfUdpStarted   = FALSE;  /* indicates whether driver started */
  62. LOCAL int ioSocket = 0;                 /* socket used to send/rcv messages */
  63. LOCAL unsigned long  myIpAddr      = 0; /* used to uniquely identify node */
  64. LOCAL unsigned long  myIpBcastAddr = 0; /* address used to broadcast packets */
  65. /* forward declarations */
  66. STATUS distIfUdpStart (void *pConf);                 /* startup function */
  67. LOCAL STATUS distIfUdpSend (DIST_NODE_ID nodeIdDest, 
  68.                             DIST_TBUF *pTBuf,
  69.                             int priority);           /* send function */
  70. LOCAL int distIfUdpIoctl (int func, ...);            /* ioctl function */
  71. LOCAL void distIfUdpInputTask (void);                /* input function */
  72. /***************************************************************************
  73. *
  74. * distIfUdpInit - initialize the UDP driver (VxFusion option)
  75. *
  76. * Initialize the UDP driver for VxFusion.
  77. *
  78. * is
  79. * i This routine initializes the UDP driver by doing the following:
  80. * Temporarily opening a socket in order to determine the IP address, netmask, 
  81. * and broadcast address for that interface.
  82. *
  83. * Filling in the DIST_IF structure which provides the upper layers with some 
  84. * necessary information about the adapter and transport 
  85. * ie
  86. *
  87. * AVAILABILITY
  88. * This routine is distributed as a component of the unbundled distributed
  89. * message queues option, VxFusion.
  90. * RETURNS: OK, or ERROR if the operation fails 
  91. */
  92. STATUS distIfUdpInit
  93.     (
  94.     void *    pConf,        /* not currently used */
  95.     FUNCPTR * pStartup      /* Ptr to startup routine */
  96.     )
  97.     {
  98.     int bsocket;           /* socket used to obtain broadcast address */
  99.     int retVal;            /* variable used to check return value */
  100.     struct ifreq ifr;      /* interface request struct for socket ioctls */
  101.     struct in_addr ifAddr; /* ip address for the interface */
  102.     struct in_addr ifMask; /* netmask for the interface*/
  103.     *pStartup = (FUNCPTR) (distIfUdpStart);
  104.     if (distIfUdpInstalled)
  105.         {
  106. #ifdef DIST_DIAGNOSTIC
  107.         printf ("distIfUdpInit() - already initalized.n");
  108. #endif
  109.         return (OK);
  110.         }
  111.     /*
  112.      * Temporarily open a socket in order to determine the node IP address, 
  113.      * netmask, and broadcast address.
  114.      */
  115.     bsocket = socket (AF_INET, SOCK_RAW, 0);
  116.     if (bsocket == -1)
  117.         {
  118.         printf ("distIfUdpInit() - can't open RAW socket (errno = %d)n",
  119.                 errno);
  120.         printf ("Unable to initialize VxFusion UDP adapter.n");
  121.         return (ERROR);
  122.         }
  123.     bzero ((char *)&ifr, sizeof (struct ifreq));
  124.     if ((strlen (pConf) + 1) > IFNAMSIZ)
  125.         {
  126.         printf ("distIfUdpInit() - interface name too long");
  127.         printf ("Unable to initialize VxFusion UDP adapter.n");
  128.         close (bsocket);
  129.         return (ERROR);
  130.         }
  131.     strcpy (ifr.ifr_name, (char *) pConf);
  132.     /* Get interface IP address */
  133.     retVal = ioctl (bsocket, (int)SIOCGIFADDR, (int)&ifr);
  134.     if (retVal != 0)
  135.         {
  136.         printf ("distIfUdpInit() - ioctl SIOCGIFADDR failed (errno = %d)n",
  137.                 errno);
  138.         printf ("Unable to initialize VxFusion UDP adapter.n");
  139.         close (bsocket);
  140.         return (ERROR);
  141.         }
  142.     ifAddr.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
  143.     myIpAddr = ntohl (ifAddr.s_addr);
  144.     /* Get interface IP Netmask */
  145.     retVal = ioctl (bsocket, (int)SIOCGIFNETMASK, (int)&ifr);
  146.     if (retVal != 0)
  147.         {
  148.         printf ("distIfUdpInit() - ioctl SIOCGIFNETMASK failed (errno=%d)n",
  149.                 errno);
  150.         printf ("Unable to initialize VxFusion UDP adapter.n");
  151.         close (bsocket);
  152.         return (ERROR);
  153.         }
  154.     ifMask.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
  155.     close (bsocket);
  156.     /*
  157.      * Extract network address and fill host portion with ones
  158.      * in order to create broadcast address.
  159.      */
  160.     myIpBcastAddr = (ifAddr.s_addr & ifMask.s_addr) | ~ifMask.s_addr;
  161.     myIpBcastAddr = ntohl (myIpBcastAddr);  
  162.     /* Fill in the distIfUdp structure */
  163.     distIfUdp.distIfName          = "UDP adapter";
  164.     distIfUdp.distIfMTU           = UDP_MTU_BUF_SZ;
  165.     distIfUdp.distIfHdrSize       = sizeof (NET_HDR);
  166.     distIfUdp.distIfBroadcastAddr = myIpBcastAddr;
  167.     distIfUdp.distIfRngBufSz      = UDP_RING_BUF_SZ;
  168.     distIfUdp.distIfMaxFrags      = UDP_MAX_FRAGS;  
  169.     distIfUdp.distIfSend          = distIfUdpSend;
  170.     distIfUdp.distIfIoctl         = distIfUdpIoctl;
  171.     pDistIf = &distIfUdp;
  172.     distIfUdpInstalled = TRUE;
  173.     printf ("VxFusion UDP adapter initialized OKn");
  174.     return (OK);
  175.     }
  176. /***************************************************************************
  177. *
  178. * distIfUdpStart - start the UDP adapter (VxFusion option)
  179. *
  180. * This routine creates a socket that is used for communications.  After
  181. * enabling the broadcast option on the socket, it spawns the input task.
  182. *
  183. * AVAILABILITY
  184. * This routine is distributed as a component of the unbundled distributed
  185. * message queues option, VxFusion.
  186. *
  187. * RETURNS: OK, or ERROR if unable to perform the socket operations or 
  188. * spawn the input task
  189. */
  190. STATUS distIfUdpStart
  191.     (
  192.     void * pConf      /* ptr to configuration data - not used here */
  193.     )
  194.     {
  195.     int optval;                       /* options value for setsockopt() */
  196.     struct sockaddr_in addrToListen;  /* socket info needed for bind() call */
  197.     
  198.     UNUSED_ARG(pConf);    
  199.     if (distIfUdpStarted)
  200.         {
  201. #ifdef DIST_DIAGNOSTIC
  202.         printf ("distIfUdpStart() - already started.n");
  203. #endif
  204.         return (OK);
  205.         }
  206.     /* Open socket */
  207.     if ((ioSocket = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
  208.         {
  209.         printf ("distIfUdpStart() - ioSocket open failed (errno = %d)n",
  210.                 errno);
  211.         printf ("Unable to start VxFusion UDP adapter.n");
  212.         return (ERROR);
  213.         }
  214.     /* Enable broadcast option for socket. */
  215.     optval = SOCKOPT_ON;
  216.     if ((setsockopt (ioSocket, SOL_SOCKET, SO_BROADCAST, (char *)&optval,
  217.                      sizeof (optval))) < 0)
  218.         {
  219.         printf ("distIfUdpStart() - setsockopt SO_BROADCAST failed ");
  220.         printf ("(errno = %d)n", errno);
  221.         printf ("Unable to start VxFusion UDP adapter.n");
  222.         close (ioSocket);
  223.         return (ERROR);
  224.         }
  225.     /* Initialize source address. */
  226.     bzero ((char *)&addrToListen, sizeof (addrToListen));
  227.     addrToListen.sin_addr.s_addr = INADDR_ANY;
  228.     addrToListen.sin_family      = AF_INET;
  229.     addrToListen.sin_port        = htons (UDP_IO_PORT);
  230.     /* Bind to the socket */
  231.       
  232.     if ((bind (ioSocket, (struct sockaddr *)&addrToListen, 
  233.                sizeof (addrToListen))) < 0)
  234.         {
  235.         printf ("distIfUdpStart() - ioSocket bind failed (errno = %d)n",
  236.                 errno);
  237.         printf ("Unable to start VxFusion UDP adapter.n");
  238.         close (ioSocket);
  239.         return (ERROR);
  240.         }
  241.     /* Spawn Input task */
  242.     if ((taskSpawn ("tDiUdpNet", 50, VX_SUPERVISOR_MODE,
  243.                     5000, (FUNCPTR) distIfUdpInputTask,
  244.                     0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
  245.         {
  246.         printf ("distIfUdpStart() - can't spawn distIfUdpInputTask task ");
  247.         printf ("(errno = %d)n", errno);
  248.         printf("Unable to start VxFusion UDP adapter.n");
  249.         close (ioSocket);
  250.         return (ERROR); /* taskSpawn() failed */    
  251.         }
  252.     distIfUdpStarted = TRUE;
  253.     printf ("VxFusion UDP adapter started OKn");
  254.     return (OK);
  255.     }
  256. /***************************************************************************
  257. *
  258. * distIfUdpInputTask - receives a broadcast and node to node messages (VxFusion option)
  259. *
  260. * The purpose of this routine is to receive a message from the network and
  261. * send it on up to the upper layers using distNetInput().
  262. *
  263. * This task does a select on a file descripter set containing the socket
  264. * file descripter.  When a message is received, it will be checked to see if 
  265. * the source of the message was this node.  If this node was the source, then
  266. * the message is discarded because the upper layers do not expect to receive
  267. * broadcast messages from itself.  NOTE: This is probably unnecessary for
  268. * in most cases as the Ethernet driver should already filter out such 
  269. * messages.
  270. *
  271. * If the message appears to be a valid message, a TBuf is allocated and the
  272. * message is copied into it.  The header fields of the TBuf are reconstructed
  273. * from the adapter specific header.  Finally, the message length is checked 
  274. * with the expected message length before sending the packet upward using
  275. * distNetInput().
  276. *
  277. * AVAILABILITY
  278. * This routine is distributed as a component of the unbundled distributed
  279. * message queues option, VxFusion.
  280. *
  281. * RETURNS: N/A
  282. *
  283. * NOMANUAL
  284. */
  285. LOCAL void distIfUdpInputTask (void)
  286.     {
  287.     char               inputMessage [UDP_MTU_BUF_SZ];  /* input buffer */
  288.     struct sockaddr_in srcAddr;      /* sender of the message */
  289.     fd_set             readFds;      /* set containing bcast & unicast sockets*/
  290.     int                msgLen;       /* length of msg received from socket */
  291.     int                srcAddrLen;   /* length of the sender's address */
  292.     DIST_NODE_ID       sourceNodeId; /* node ID of the sender */
  293.     NET_HDR *          pUdpHdr;      /* ptr to msg's adapter specific header */
  294.     DIST_TBUF *        pTBuf;        /* ptr to buffer msg will be copied into */
  295.     /* Initialize source address. */
  296.     bzero ((char *)&srcAddr, sizeof (srcAddr));
  297.     srcAddr.sin_addr.s_addr = INADDR_ANY;
  298.     srcAddr.sin_family =      AF_INET;
  299.     srcAddrLen = sizeof (srcAddr);
  300.     FOREVER 
  301.         {
  302.         FD_ZERO (&readFds);
  303.         FD_SET (ioSocket, &readFds);
  304.         if ((select (FD_SETSIZE, &readFds, NULL, NULL, NULL)) < 0)
  305.             {
  306.             close (ioSocket);
  307. #ifdef DIST_DIAGNOSTIC
  308.             printf ("distIfUdpInputTask() - select returned an errorn");
  309. #endif
  310.             return;
  311.             }
  312.         distStat.ifInReceived++;
  313.         if ((msgLen = recvfrom (ioSocket, (caddr_t) &inputMessage, 
  314.                                 sizeof (inputMessage), 0, (struct sockaddr *) 
  315.                                 &srcAddr, &srcAddrLen)) < 0)
  316.             {
  317. #ifdef DIST_DIAGNOSTIC
  318.             printf ("distIfUdpInputTask() - got an error from recvfromn");
  319. #endif
  320.             distStat.ifInDiscarded++;
  321.             continue; /* Skip for now */
  322.             }
  323.         /* Check for buffer too small */
  324.         if (msgLen < sizeof (NET_HDR))
  325.             {
  326. #ifdef DIST_DIAGNOSTIC
  327.             printf ("distIfUdpInputTask() - got packet which is too smalln");
  328. #endif
  329.             distStat.ifInLength++;
  330.             distStat.ifInDiscarded++;
  331.             continue;
  332.             }
  333.         /* Get node ID */
  334.         sourceNodeId = ntohl (srcAddr.sin_addr.s_addr);
  335.         /* 
  336.          * If this packet is a broadcast that was sent from this node, we
  337.          * may get a copy of the packet if it isn't discarded by the 
  338.          * ethernet driver.  If it isn't discarded by the ethernet driver, 
  339.          * we need to discard broadcast packets sent from ourself.
  340.          */
  341.         pUdpHdr = (NET_HDR *) inputMessage;
  342.         if ( ( ntohs (pUdpHdr->pktFlags) & DIST_TBUF_FLAG_BROADCAST) && 
  343.             (myIpAddr == sourceNodeId))
  344.             {
  345. #ifdef DIST_DIAGNOSTIC
  346.             printf ("distIfUdpInputTask() - discarded loop broadcastn");
  347. #endif
  348.             distStat.ifInDiscarded++;
  349.             continue;
  350.             }
  351.         /* Allocate Input buffer */
  352.         if ((pTBuf = distTBufAlloc ()) == NULL)
  353.             {
  354. #ifdef DIST_DIAGNOSTIC
  355.             printf ("distIfUdpInputTask() - failed to allocate a buffern");
  356. #endif
  357.             distStat.ifInDiscarded++;
  358.             continue;
  359.             }
  360.         bcopy (inputMessage,
  361.                ((char *)pTBuf->pTBufData - sizeof (NET_HDR)),
  362.                msgLen);
  363.         pUdpHdr = (NET_HDR *) ((char *)pTBuf->pTBufData - sizeof (NET_HDR));
  364.         pTBuf->tBufId     = ntohs (pUdpHdr->pktId);
  365.         pTBuf->tBufAck    = ntohs (pUdpHdr->pktAck);
  366.         pTBuf->tBufSeq    = ntohs (pUdpHdr->pktFragSeq);
  367.         pTBuf->tBufNBytes = ntohs (pUdpHdr->pktLen);
  368.         pTBuf->tBufType   = ntohs (pUdpHdr->pktType);
  369.         pTBuf->tBufFlags  = ntohs (pUdpHdr->pktFlags);
  370.         /*
  371.          * Check for the right packet length.  The packet length
  372.          * should be equivalent to the sum of the number of bytes
  373.          * in the data portion and the size of the adapter specific
  374.          * header (NET_HDR for UDP). 
  375.          */
  376.         if ((pTBuf->tBufNBytes + sizeof (NET_HDR)) != msgLen)
  377.             {
  378. #ifdef DIST_DIAGNOSTIC
  379.             printf ("distIfUdpInputTask() - invalid packet lengthn");
  380. #endif
  381.             distTBufFree (pTBuf);
  382.             distStat.ifInLength++;
  383.             distStat.ifInDiscarded++;
  384.             continue;
  385.             }
  386. #ifdef DIST_DIAGNOSTIC
  387.         printf ("distIfUdpInputTask() - got a packet (type %d) from 0x%lxn",
  388.                pTBuf->tBufType, sourceNodeId);
  389. #endif
  390.         /* Send the packet up the stack */
  391.         distNetInput (sourceNodeId, ntohs (pUdpHdr->priority), pTBuf);
  392.         } /* end FOREVER */
  393. #if 0   /* someday, we might actually break out of FOREVER */
  394.     close (ioSocket); 
  395.     return;
  396. #endif
  397.     }
  398. /***************************************************************************
  399. *
  400. * distIfUdpSend - convert header to network byte order and send packet out (VxFusion option)
  401. *
  402. * This routine fills in the adapter specific header using the information
  403. * in the TBuf and then sends the packet out.
  404. *
  405. * The calling routine will free the TBuf passed to distIfUdpSend().  While
  406. * this implies that the TBuf does not need to be freed here, it also 
  407. * implies that this routine must finish using the TBuf before it returns.
  408. * AVAILABILITY
  409. * This routine is distributed as a component of the unbundled distributed
  410. * message queues option, VxFusion.
  411. *
  412. * RETURNS: OK, or ERROR if the operation fails 
  413. *
  414. * NOMANUAL
  415. */
  416. LOCAL STATUS distIfUdpSend
  417.     (
  418.     DIST_NODE_ID    nodeIdDest,     /* destination node */
  419.     DIST_TBUF *     pTBuf,          /* TBuf to send */
  420.     int             priority        /* packet priority */
  421.     )
  422.     {
  423.     NET_HDR *           pUdpHdr;
  424.     struct  sockaddr_in dstAddr;
  425.     distStat.ifOutReceived++;
  426.     /* Access pre-allocated UDP NET_HDR header from data buffer */
  427.     pUdpHdr = (NET_HDR *) ((char *)pTBuf->pTBufData - sizeof (NET_HDR));
  428.     pUdpHdr->pktId = htons (pTBuf->tBufId);       /* packet ID */
  429.     pUdpHdr->pktAck = htons (pTBuf->tBufAck);     /* last packet ID acked */
  430.     pUdpHdr->pktFragSeq = htons (pTBuf->tBufSeq); /* fragmented seq number */
  431.     pUdpHdr->pktLen = htons (pTBuf->tBufNBytes);  /* packet length */
  432.     pUdpHdr->pktType = htons (pTBuf->tBufType);   /* pkt type(DATA,ACK,...)*/
  433.     pUdpHdr->pktFlags = htons (pTBuf->tBufFlags); /* flgs: HDR,MORE_MF,BCAST*/
  434.     pUdpHdr->priority = htons ((short)priority);  /* packet priority */
  435.     dstAddr.sin_family = AF_INET;
  436.     dstAddr.sin_addr.s_addr = htonl (nodeIdDest);
  437.     dstAddr.sin_port   = htons (UDP_IO_PORT);
  438. #ifdef DIST_DIAGNOSTIC
  439.     printf ("distIfUdpSend() - sending a packet (type %d) to =0x%lxn",
  440.             pTBuf->tBufType, nodeIdDest);
  441. #endif
  442.     /* Send the packet out */
  443.     if ((sendto (ioSocket, (caddr_t) pUdpHdr, 
  444.                  (pTBuf->tBufNBytes + sizeof (NET_HDR)), 0, 
  445.                  (struct sockaddr *) &dstAddr, sizeof (dstAddr))) < 0)
  446.         {
  447. #ifdef DIST_DIAGNOSTIC
  448.         printf ("distIfUdpSend() - sendto() failedn");
  449. #endif
  450.         return (ERROR);
  451.         }
  452.     return (OK);
  453.     }
  454. /***************************************************************************
  455. *
  456. * distIfUdpIoctl - I/O control function for the adapter (VxFusion option)
  457. *
  458. * This is the I/O control function for the UDP adapter.  Since the UDP
  459. * adapter does not currently implement any control functions, this function
  460. * will simply return ERROR in response to any call.
  461. *
  462. * AVAILABILITY
  463. * This routine is distributed as a component of the unbundled distributed
  464. * message queues option, VxFusion.
  465. *
  466. * RETURNS: ERROR only
  467. *
  468. * NOMANUAL
  469. */
  470. LOCAL int distIfUdpIoctl
  471.     (
  472.     int func,   /* control function to perform */
  473.     ...         /* optional arguments */
  474.     )
  475.     {
  476.        
  477.     UNUSED_ARG(func);
  478.     
  479.     return (ERROR);
  480.     }