Subversion Repositories HomeAutomation

Rev

Rev 363 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*********************************************************************
  2.  *
  3.  *                  PIC IP Module for Microchip TCP/IP Stack
  4.  *
  5.  *********************************************************************
  6.  * FileName:        IP.C
  7.  * Dependencies:    string.h
  8.  *                  StackTsk.h
  9.  *                  Helpers.h
  10.  *                  IP.h
  11.  * Processor:       PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
  12.  * Complier:        Microchip C18 v3.02 or higher
  13.  *                  Microchip C30 v2.01 or higher
  14.  * Company:         Microchip Technology, Inc.
  15.  *
  16.  * Software License Agreement
  17.  *
  18.  * This software is owned by Microchip Technology Inc. ("Microchip")
  19.  * and is supplied to you for use exclusively as described in the
  20.  * associated software agreement.  This software is protected by
  21.  * software and other intellectual property laws.  Any use in
  22.  * violation of the software license may subject the user to criminal
  23.  * sanctions as well as civil liability.  Copyright 2006 Microchip
  24.  * Technology Inc.  All rights reserved.
  25.  *
  26.  * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL
  27.  * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
  28.  * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
  29.  * INFRINGEMENT.  Microchip shall in no event be liable for special,
  30.  * incidental, or consequential damages.
  31.  *
  32.  *
  33.  * Author               Date    Comment
  34.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35.  * Nilesh Rajbharti     4/27/01 Original        (Rev 1.0)
  36.  * Nilesh Rajbharti     2/9/02  Cleanup
  37.  * Nilesh Rajbharti     5/22/02 Rev 2.0 (See version.log for detail)
  38.  * Howard Schlunder     8/31/04 Beta Rev 0.9 (See version.log for detail)
  39.  * Howard Schlunder     1/5/06  Improved DMA checksum efficiency
  40.  ********************************************************************/
  41.  
  42. #include <string.h>
  43.  
  44. #include "..\Include\StackTsk.h"
  45. #include "..\Include\Helpers.h"
  46. #include "..\Include\MAC.h"
  47. #include "..\Include\IP.h"
  48.  
  49. // This is left shifted by 4.  Actual value is 0x04.
  50. #define IPv4                (0x40u)
  51. #define IP_VERSION          IPv4
  52.  
  53. // IHL (Internet Header Length) is # of DWORDs in a header.
  54. // Since, we do not support options, our IP header length will be
  55. // minimum i.e. 20 bytes : IHL = 20 / 4 = 5.
  56. #define IP_IHL              (0x05)
  57.  
  58. #define IP_SERVICE_NW_CTRL  (0x07)
  59. #define IP_SERVICE_IN_CTRL  (0x06)
  60. #define IP_SERVICE_ECP      (0x05)
  61. #define IP_SERVICE_OVR      (0x04)
  62. #define IP_SERVICE_FLASH    (0x03)
  63. #define IP_SERVICE_IMM      (0x02)
  64. #define IP_SERVICE_PRIOR    (0x01)
  65. #define IP_SERVICE_ROUTINE  (0x00)
  66.  
  67. #define IP_SERVICE_N_DELAY  (0x00)
  68. #define IP_SERCICE_L_DELAY  (0x08)
  69. #define IP_SERVICE_N_THRPT  (0x00)
  70. #define IP_SERVICE_H_THRPT  (0x10)
  71. #define IP_SERVICE_N_RELIB  (0x00)
  72. #define IP_SERVICE_H_RELIB  (0x20)
  73.  
  74. #define IP_SERVICE          (IP_SERVICE_ROUTINE | IP_SERVICE_N_DELAY)
  75.  
  76. #define MY_IP_TTL           (100)  // Time-To-Live in Seconds
  77.  
  78.  
  79.  
  80.  
  81. static WORD _Identifier = 0;
  82. static BYTE IPHeaderLen;
  83.  
  84.  
  85. static void SwapIPHeader(IP_HEADER* h);
  86.  
  87.  
  88.  
  89.  
  90. /*********************************************************************
  91.  * Function:        BOOL IPGetHeader( IP_ADDR    *localIP,
  92.  *                                    NODE_INFO  *remote,
  93.  *                                    BYTE        *Protocol,
  94.  *                                    WORD        *len)
  95.  *
  96.  * PreCondition:    MACGetHeader() == TRUE
  97.  *
  98.  * Input:           localIP     - Local node IP Address as received
  99.  *                                in current IP header.
  100.  *                                If this information is not required
  101.  *                                caller may pass NULL value.
  102.  *                  remote      - Remote node info
  103.  *                  Protocol    - Current packet protocol
  104.  *                  len         - Current packet data length
  105.  *
  106.  * Output:          TRUE, if valid packet was received
  107.  *                  FALSE otherwise
  108.  *
  109.  * Side Effects:    None
  110.  *
  111.  * Note:            Only one IP message can be received.
  112.  *                  Caller may not transmit and receive a message
  113.  *                  at the same time.
  114.  *
  115.  ********************************************************************/
  116. BOOL IPGetHeader(IP_ADDR *localIP,
  117.                  NODE_INFO *remote,
  118.                  BYTE *protocol,
  119.                  WORD *len)
  120. {
  121.     WORD_VAL    CalcChecksum;
  122.     IP_HEADER   header;
  123.  
  124. #if defined(NON_MCHP_MAC)
  125.     WORD_VAL    ReceivedChecksum;
  126.     WORD        checksums[2];
  127.     BYTE        optionsLen;
  128. #define MAX_OPTIONS_LEN     (40)            // As per RFC 791.
  129.     BYTE        options[MAX_OPTIONS_LEN];
  130. #endif
  131.  
  132.     // Read IP header.
  133.     MACGetArray((BYTE*)&header, sizeof(header));
  134.  
  135.     // Make sure that this is an IPv4 packet.
  136.     if ( (header.VersionIHL & 0xf0) != IP_VERSION )
  137.         return FALSE;
  138.  
  139. #if !defined(NON_MCHP_MAC)
  140.     IPHeaderLen = (header.VersionIHL & 0x0f) << 2;
  141.    
  142.     // Validate the IP header.  If it is correct, the checksum
  143.     // will come out to 0x0000 (because the header contains a
  144.     // precomputed checksum).  A corrupt header will have a
  145.     // nonzero checksum.
  146.     CalcChecksum.Val = MACCalcRxChecksum(0, IPHeaderLen);
  147.  
  148.     // Seek to the end of the IP header
  149.     MACSetRxBuffer(IPHeaderLen);   
  150.  
  151.     if(CalcChecksum.Val)
  152. #else
  153.    
  154.     // Calculate options length in this header, if there is any.
  155.     // IHL is in terms of numbers of 32-bit DWORDs; i.e. actual
  156.     // length is 4 times IHL.
  157.     optionsLen = ((header.VersionIHL & 0x0f) << 2) - sizeof(header);
  158.  
  159.     // If there is any option(s), read it so that we can include them
  160.     // in checksum calculation.
  161.     if ( optionsLen > MAX_OPTIONS_LEN )
  162.         return FALSE;
  163.  
  164.     if ( optionsLen > 0 )
  165.         MACGetArray(options, optionsLen);
  166.  
  167.     // Save header checksum; clear it and recalculate it ourselves.
  168.     ReceivedChecksum.Val = header.HeaderChecksum;
  169.     header.HeaderChecksum = 0;
  170.  
  171.     // Calculate checksum of header including options bytes.
  172.     checksums[0] = ~CalcIPChecksum((BYTE*)&header, sizeof(header));
  173.  
  174.     // Calculate Options checksum too, if they are present.
  175.     if ( optionsLen > 0 )
  176.         checksums[1] = ~CalcIPChecksum((BYTE*)options, optionsLen);
  177.     else
  178.         checksums[1] = 0;
  179.  
  180.     CalcChecksum.Val  = CalcIPChecksum((BYTE*)checksums,
  181.                                             2 * sizeof(WORD));
  182.  
  183.     // Make sure that checksum is correct
  184.     if ( ReceivedChecksum.Val != CalcChecksum.Val )
  185. #endif
  186.     {
  187.         // Bad packet. The function caller will be notified by means of the FALSE
  188.         // return value and it should discard the packet.
  189.         return FALSE;
  190.     }
  191.  
  192.     // Network to host conversion.
  193.     SwapIPHeader(&header);
  194.  
  195.     // If caller is intrested, return destination IP address
  196.     // as seen in this IP header.
  197.     if ( localIP )
  198.         localIP->Val    = header.DestAddress.Val;
  199.  
  200.     remote->IPAddr.Val  = header.SourceAddress.Val;
  201.     *protocol           = header.Protocol;
  202. #if !defined(NON_MCHP_MAC)
  203.     *len                = header.TotalLength - IPHeaderLen;
  204. #else
  205.     *len                = header.TotalLength - optionsLen -
  206.                             sizeof(header);
  207. #endif                          
  208.  
  209.     return TRUE;
  210. }
  211.  
  212.  
  213.  
  214.  
  215. /*********************************************************************
  216.  * Function: WORD IPPutHeader(NODE_INFO *remote,
  217.  *                            BYTE protocol,
  218.  *                            WORD len)
  219.  *
  220.  * PreCondition:    IPIsTxReady() == TRUE
  221.  *
  222.  * Input:           *remote     - Destination node address
  223.  *                  protocol    - Current packet protocol
  224.  *                  len         - Current packet data length
  225.  *
  226.  * Output:          (WORD)0
  227.  *
  228.  * Side Effects:    None
  229.  *
  230.  * Note:            Only one IP message can be transmitted at any
  231.  *                  time.
  232.  ********************************************************************/
  233. WORD IPPutHeader(NODE_INFO *remote,
  234.                  BYTE protocol,
  235.                  WORD len)
  236. {
  237.     IP_HEADER   header;
  238.    
  239.     IPHeaderLen = sizeof(IP_HEADER);
  240.  
  241.     header.VersionIHL       = IP_VERSION | IP_IHL;
  242.     header.TypeOfService    = IP_SERVICE;
  243.     header.TotalLength      = sizeof(header) + len;
  244.     header.Identification   = ++_Identifier;
  245.     header.FragmentInfo     = 0;
  246.     header.TimeToLive       = MY_IP_TTL;
  247.     header.Protocol         = protocol;
  248.     header.HeaderChecksum   = 0;
  249.     header.SourceAddress    = AppConfig.MyIPAddr;
  250.  
  251.     header.DestAddress.Val = remote->IPAddr.Val;
  252.  
  253.     SwapIPHeader(&header);
  254.  
  255. #if defined(NON_MCHP_MAC)
  256.     header.HeaderChecksum   = CalcIPChecksum((BYTE*)&header,
  257.                                                 sizeof(header));
  258. #endif
  259.  
  260.     MACPutHeader(&remote->MACAddr, MAC_IP, (sizeof(header)+len));
  261.     MACPutArray((BYTE*)&header, sizeof(header));
  262.  
  263. #if !defined(NON_MCHP_MAC)
  264.     header.HeaderChecksum = MACCalcTxChecksum(0, sizeof(header));
  265.     MACSetTxBuffer(CurrentTxBuffer, 10);    // 10 is the offset in header to the HeaderChecksum member
  266.     MACPutArray((BYTE*)&header.HeaderChecksum, 2);
  267.     MACSetTxBuffer(CurrentTxBuffer, sizeof(header));    // Seek back to the end of the packet
  268. #endif 
  269.    
  270.     return 0x0;
  271.  
  272. }
  273.  
  274. /*********************************************************************
  275.  * Function:        IPSetRxBuffer(WORD Offset)
  276.  *
  277.  * PreCondition:    IPHeaderLen must have been intialized by
  278.  *                  IPGetHeader() or IPPutHeader()
  279.  *
  280.  * Input:           Offset from beginning of IP data field
  281.  *
  282.  * Output:          Next Read/Write access to receive buffer is
  283.  *                  set to Offset
  284.  *
  285.  * Side Effects:    None
  286.  *
  287.  * Note:            None
  288.  *
  289.  ********************************************************************/
  290. void IPSetRxBuffer(WORD Offset)
  291. {
  292.     MACSetRxBuffer(Offset+IPHeaderLen);
  293. }
  294.  
  295.  
  296.  
  297. static void SwapIPHeader(IP_HEADER* h)
  298. {
  299.     h->TotalLength      = swaps(h->TotalLength);
  300.     h->Identification   = swaps(h->Identification);
  301.     h->HeaderChecksum   = swaps(h->HeaderChecksum);
  302. }
  303.