openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

shr_pkt.c (9717B)


      1 /* 
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        shr_pkt.c
      8  * Purpose:     Common pkt pack/unpack routines and pkt utility
      9  *              functions.
     10  */
     11 #include <soc/shared/shr_pkt.h>
     12 
     13 /*
     14  * Functions:
     15  *      shr_<header>_pack
     16  * Purpose:
     17  *      The following set of _pack() functions packs in
     18  *      network byte order a given header.
     19  * Parameters:
     20  *      buffer          - (OUT) Buffer where to pack header.
     21  *      <header>        - (IN) Header to pack.
     22  * Returns:
     23  *      Pointer to next position in buffer.
     24  * Notes:
     25  */
     26 
     27 uint8 *
     28 shr_lb_header_pack(uint8 *buffer, shr_lb_header_t *lb)
     29 {
     30     uint32  tmp;
     31 
     32     tmp = (lb->start << 24) | ((lb->input_pri & 0xF) << 20) |
     33         ((lb->common_hdr0 & 0xF) << 16) | ((lb->common_hdr1 & 0x1) << 15) |
     34         ((lb->source_type & 0x1) << 14) | ((lb->source0 & 0x3F) << 8) |
     35         lb->source1;
     36     SHR_PKT_PACK_U32(buffer, tmp);
     37 
     38     tmp = ((lb->source2 & 0x3) << 30) | ((lb->visibility & 0x1) << 29) |
     39         ((lb->pkt_profile & 0x7) << 26) | ((lb->reserved0_0 & 0x3) << 24) |
     40         (lb->reserved0_1 << 16) | (lb->reserved1_0 << 8) |
     41         ((lb->reserved1_1 & 0x3) << 6) | ((lb->zero & 0x1) << 5) | (lb->reserved2 & 0x1F);
     42     SHR_PKT_PACK_U32(buffer, tmp);
     43 
     44     tmp = (lb->reserved3 << 24) | (lb->reserved4 << 16) | (lb->reserved5 << 8) |
     45         lb->reserved6;
     46     SHR_PKT_PACK_U32(buffer, tmp);
     47 
     48     tmp = (lb->reserved7 << 24) | (lb->reserved8 << 16) | (lb->reserved9 << 8) |
     49         lb->pp_port;
     50     SHR_PKT_PACK_U32(buffer, tmp);
     51 
     52     return buffer;
     53 }
     54 
     55 uint8 *
     56 shr_int_header_pack(uint8 *buffer, shr_int_header_t *int_h)
     57 {
     58     uint32  tmp;
     59 
     60     SHR_PKT_PACK_U32(buffer, int_h->probemarker1);
     61     SHR_PKT_PACK_U32(buffer, int_h->probemarker2);
     62 
     63     tmp = (int_h->ver << 24) | (int_h->type << 16) | int_h->flags;
     64     SHR_PKT_PACK_U32(buffer, tmp);
     65 
     66     SHR_PKT_PACK_U32(buffer, int_h->requestvector);
     67 
     68     tmp = (int_h->hoplimit << 24) | (int_h->hopcount << 16) | int_h->mustbezeros;
     69     SHR_PKT_PACK_U32(buffer, tmp);
     70 
     71     tmp = (int_h->maximumlength << 16) | int_h->currentlength;
     72     SHR_PKT_PACK_U32(buffer, tmp);
     73 
     74     tmp = (int_h->senderhandle << 16) | int_h->seqnumber;
     75     SHR_PKT_PACK_U32(buffer, tmp);
     76 
     77     return buffer;
     78 }
     79 
     80 uint8 *
     81 shr_udp_header_pack(uint8 *buffer, shr_udp_header_t *udp)
     82 {
     83    SHR_PKT_PACK_U16(buffer, udp->src);
     84    SHR_PKT_PACK_U16(buffer, udp->dst);
     85    SHR_PKT_PACK_U16(buffer, udp->length);
     86    SHR_PKT_PACK_U16(buffer, udp->sum);
     87 
     88     return buffer;
     89 }
     90 
     91 uint8 *
     92 shr_ipv4_header_pack(uint8 *buffer, shr_ipv4_header_t *ip)
     93 {
     94     uint32  tmp;
     95 
     96     tmp = ((ip->version & 0xf) << 28) | ((ip->h_length & 0xf) << 24) |
     97         ((ip->dscp & 0x3f) << 18) | ((ip->ecn & 0x3)<< 16) | (ip->length);
     98     SHR_PKT_PACK_U32(buffer, tmp);
     99 
    100     tmp = (ip->id << 16) | ((ip->flags & 0x7) << 13) | (ip->f_offset & 0x1fff);
    101     SHR_PKT_PACK_U32(buffer, tmp);
    102 
    103     tmp = (ip->ttl << 24) | (ip->protocol << 16) | ip->sum;
    104     SHR_PKT_PACK_U32(buffer, tmp);
    105 
    106     SHR_PKT_PACK_U32(buffer, ip->src);
    107     SHR_PKT_PACK_U32(buffer, ip->dst);
    108 
    109     return buffer;
    110 }
    111 
    112 uint8 *
    113 shr_ipv6_header_pack(uint8 *buffer, shr_ipv6_header_t *ip)
    114 {
    115     uint32  tmp;
    116     int     i;
    117 
    118     tmp = ((ip->version & 0xf) << 28) | (ip->t_class << 20) |
    119         (ip->f_label & 0xfffff);
    120     SHR_PKT_PACK_U32(buffer, tmp);
    121 
    122     tmp = (ip->p_length << 16 ) | (ip->next_header << 8) | ip->hop_limit;
    123     SHR_PKT_PACK_U32(buffer, tmp);
    124 
    125     for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
    126         SHR_PKT_PACK_U8(buffer, ip->src[i]);
    127     }
    128 
    129     for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
    130         SHR_PKT_PACK_U8(buffer, ip->dst[i]);
    131     }
    132 
    133     return buffer;
    134 }
    135 
    136 uint8 *
    137 shr_gre_header_pack(uint8 *buffer, shr_gre_header_t *gre)
    138 {
    139     uint32  tmp;
    140 
    141     tmp = ((gre->checksum & 0x1) << 31) | ((gre->routing & 0x1) << 30) |
    142         ((gre->key & 0x1) << 29) | ((gre->sequence_num & 0x1) << 28) | 
    143         ((gre->strict_src_route & 0x1) << 27) |
    144         ((gre->recursion_control & 0x7) << 24) | ((gre->flags & 0x1f) << 19) |
    145         ((gre->version & 0x7) << 16) | (gre->protocol & 0xffff);
    146 
    147     SHR_PKT_PACK_U32(buffer, tmp);
    148 
    149     return buffer;
    150 }
    151 
    152 uint8 *
    153 shr_ach_header_pack(uint8 *buffer, shr_ach_header_t *ach)
    154 {
    155     uint32  tmp;
    156 
    157     tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) |
    158         (ach->reserved << 16) | ach->channel_type;
    159 
    160     SHR_PKT_PACK_U32(buffer, tmp);
    161 
    162     return buffer;
    163 }
    164 
    165 uint8 *
    166 shr_mpls_label_pack(uint8 *buffer, shr_mpls_label_t *mpls)
    167 {
    168     uint32  tmp;
    169 
    170     tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) |
    171         ((mpls->s & 0x1) << 8) | mpls->ttl;
    172     SHR_PKT_PACK_U32(buffer, tmp);
    173 
    174     return buffer;
    175 }
    176 
    177 uint8 *
    178 shr_l2_header_pack(uint8 *buffer, shr_l2_header_t *l2)
    179 {
    180     uint32  tmp;
    181     int     i;
    182 
    183     for (i = 0; i < SHR_MAC_ADDR_LENGTH; i++) {
    184         SHR_PKT_PACK_U8(buffer, l2->dst_mac[i]);
    185     }
    186 
    187     for (i = 0; i < SHR_MAC_ADDR_LENGTH; i++) {
    188         SHR_PKT_PACK_U8(buffer, l2->src_mac[i]);
    189     }
    190 
    191     /*
    192      * VLAN Tag
    193      *
    194      * A TPID value of 0 indicates this is an untagged frame.
    195      */
    196     if (l2->outer_vlan_tag.tpid != 0) {
    197         /* Add VLAN tag */
    198         tmp = (l2->outer_vlan_tag.tpid << 16) |
    199             ((l2->outer_vlan_tag.tci.prio & 0x7) << 13) |
    200             ((l2->outer_vlan_tag.tci.cfi & 0x1) << 12) |
    201             (l2->outer_vlan_tag.tci.vid & 0xfff);
    202         SHR_PKT_PACK_U32(buffer, tmp);
    203     }
    204 
    205     /* Packet inner vlan tag */
    206 
    207     if (l2->inner_vlan_tag.tpid != 0) {
    208         /* Add VLAN tag */
    209         tmp = (l2->inner_vlan_tag.tpid << 16) |
    210             ((l2->inner_vlan_tag.tci.prio & 0x7) << 13) |
    211             ((l2->inner_vlan_tag.tci.cfi & 0x1) << 12) |
    212             (l2->inner_vlan_tag.tci.vid & 0xfff);
    213         SHR_PKT_PACK_U32(buffer, tmp);
    214     }
    215 
    216     SHR_PKT_PACK_U16(buffer, l2->etype);
    217 
    218     return buffer;
    219 }
    220 
    221 uint8 *
    222 shr_ipfix_header_pack(uint8 *buffer, shr_ipfix_header_t *ipfix)
    223 {
    224     SHR_PKT_PACK_U16(buffer, ipfix->version);
    225     SHR_PKT_PACK_U16(buffer, ipfix->length);
    226     SHR_PKT_PACK_U32(buffer, ipfix->export_time);
    227     SHR_PKT_PACK_U32(buffer, ipfix->sequence_num);
    228     SHR_PKT_PACK_U32(buffer, ipfix->observation_id);
    229 
    230     return buffer;
    231 }
    232 
    233 /*
    234  * Function:
    235  *      shr_initial_chksum_get
    236  * Purpose:
    237  *      Get the initial checksum
    238  *
    239  *      Return the partial checksum as uint32 value. This routine simply adds up
    240  *      the data as 16 bit words. The final 16 bit checksum has to be calculated
    241  *      later.
    242  * Parameters:
    243  *      length             - (IN) Length of the data buffer
    244  *      data               - (IN) Data buffer
    245  * Returns:
    246  *      Initial checksum
    247  */
    248 uint32
    249 shr_initial_chksum_get(uint16 length, uint8 *data)
    250 {
    251     uint32  chksum = 0;
    252     uint16  w16;
    253     int     i = 0;
    254 
    255     while (length > 1) {
    256         w16 = (((uint16)data[i]) << 8) + data[i+1];
    257         chksum += w16;
    258         i+=2;
    259         length -= 2;
    260     }
    261     if (length) {
    262         w16 = (((uint16)data[i]) << 8) + 0;
    263         chksum += w16;
    264     }
    265 
    266     return (chksum);
    267 }
    268 
    269 /*
    270  * Function:
    271  *      shr_udp_initial_checksum_get
    272  * Purpose:
    273  *      Get the UDP initial checksum (excludes checksum for the data).
    274  *
    275  *      The checksum includes the IP pseudo-header and UDP header.
    276  *      It does not include the checksum for the data.
    277  *      The data checksum will be added to UDP initial checksum
    278  *      each time a packet is sent, since data payload may vary.
    279  * Parameters:
    280  *      v6              - (IN) Set if IP is IPv6.
    281  *      ipv4            - (IN) IPv4 header.
    282  *      ipv6            - (IN) IPv6 header.
    283  *      payload         - (IN) UDP payload.
    284  *      udp             - (IN/OUT) UDP header checksum to update.
    285  * Returns:
    286  *      Initial checksum
    287  */
    288 uint32
    289 shr_udp_initial_checksum_get(int v6,
    290                              shr_ipv4_header_t *ipv4,
    291                              shr_ipv6_header_t *ipv6,
    292                              uint8 *payload,
    293                              shr_udp_header_t  *udp)
    294 {
    295     uint8  buffer[SHR_UDP_HEADER_LENGTH + (BCM_IP6_ADDRLEN*2) + 8 + SHR_UDP_PAYLOAD_LENGTH];
    296     uint8  *cur_ptr = buffer;
    297     int    i, length;
    298 
    299     /* Build IP Pseudo-Header */
    300     if (v6) {
    301         /* IPv6 Pseudo-Header
    302          *     Source address
    303          *     Destination address
    304          *     UDP length  (32-bit)
    305          *     Next Header (lower 8 bits of 32-bit)
    306          */
    307         for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
    308             SHR_PKT_PACK_U8(cur_ptr, ipv6->src[i]);
    309         }
    310         for (i = 0; i < BCM_IP6_ADDRLEN; i++) {
    311             SHR_PKT_PACK_U8(cur_ptr, ipv6->dst[i]);
    312         }
    313 
    314         SHR_PKT_PACK_U16(cur_ptr, udp->length);
    315         SHR_PKT_PACK_U8(cur_ptr, 0);
    316         SHR_PKT_PACK_U8(cur_ptr, ipv6->next_header);
    317     } else {
    318         /* IPv4 Pseudo-Header
    319          *     Source address
    320          *     Destination address
    321          *     Protocol    (8 bits)
    322          *     UDP length  (16-bit)
    323          */
    324         SHR_PKT_PACK_U32(cur_ptr, ipv4->src);
    325         SHR_PKT_PACK_U32(cur_ptr, ipv4->dst);
    326         /*
    327          * Added 0 before protcol value to compute checksum
    328          * accurately
    329          */
    330         SHR_PKT_PACK_U8(cur_ptr, 0);
    331         SHR_PKT_PACK_U8(cur_ptr, ipv4->protocol);
    332         SHR_PKT_PACK_U16(cur_ptr, udp->length);
    333     }
    334 
    335     /* Add UDP header */
    336     cur_ptr = shr_udp_header_pack(cur_ptr, udp);
    337 
    338     /* Add payload */
    339     if (payload != NULL) {
    340         length = udp->length - SHR_UDP_HEADER_LENGTH;
    341         for (i = 0; i < length; i++) {
    342             SHR_PKT_PACK_U8(cur_ptr, payload[i]);
    343         }
    344     }
    345 
    346     /* Calculate initial UDP checksum */
    347     length = cur_ptr - buffer;
    348     return shr_initial_chksum_get(length, buffer);
    349 }