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 }